Frage

Ich verwende Duck Typing in Python.

def flagItem(object_to_flag, account_flagging, flag_type, is_flagged):
    if flag_type == Flags.OFFENSIVE:
        object_to_flag.is_offensive=is_flagged
    elif flag_type == Flags.SPAM:
        object_to_flag.is_spam=is_flagged
    object_to_flag.is_active=(not is_flagged)
    object_to_flag.cleanup()
    return object_to_flag.put()

Wenn verschiedene Objekte in als object_to_flag übergeben werden, von denen alle haben is_active, is_spam, is_offensive Attribute. Sie passieren auch eine cleanup() Methode haben.

Die Objekte Ich bin in allen vorbei haben die gleiche Basisklasse (sie sind db Objekte in Google App Engine):

class User(db.Model):
    ...
    is_active = db.BooleanProperty(default = True)
    is_spam = db.BooleanProperty(default=False)
    is_offensive = db.BooleanProperty(default=False)
    def cleanup():
        pass

class Post(db.Model):
    ...
    is_active = db.BooleanProperty(default = True)
    is_spam = db.BooleanProperty(default=False)
    is_offensive = db.BooleanProperty(default=False)
    def cleanup():
        pass

Wie kann ich die cleanup() Methode abstrakt so machen, dass ich die gleiche Elternklasse für all diese Objekte haben kann, dass die Kinder Implementierung erfordert zur Verfügung stellen?

Vielleicht noch wichtiger ist, ist diese 'pythonic'? Soll ich diesen Weg gehen, oder soll ich vertrauen einfach auf der Ente eingeben? Mein Hintergrund ist in Java und ich versuche, die Python-Art, die Dinge zu lernen.

Danke!

War es hilfreich?

Lösung

Da Sie nicht über abc verfügbar, können Sie dies mit einem einfachen tun können metaclass

class Abstract(type(db.Model)):
    def __new__(metacls, clsname, bases, clsdict):
        for methodname in clsdict.pop('_abstract_methods_', []):
            try:
                if not callable(clsdict[methodname]):
                    raise TypeError("{0} must implement {1}".format(clcname, methodname))
            except KeyError:
                raise TypeError("{0} must implement {1}".format(clcname, methodname))
       return super(Abstract, metacls).__new__(metacls, clsname, bases, clsdict)


class RequireCleanup(db.Model):
    __metaclass__ = Abstract
    _abstract_methods_ = ['cleanup']

    def cleanup(self):
        pass

der Ausdruck type(db.Model) Entschlüssen, was auch immer Metaklasse für db.Model verwendet wird, so dass wir auf den Google-Code nicht Schritt tun. Außerdem machen wir einen Abstecher _abstract_methods_ aus der Klasse Wörterbuch bevor es bekommen vergangen ist __new__ Methode Google, so dass wir nichts brechen. Wenn db.Model bereits ein Attribut mit diesem Namen hat, dann müssen Sie es auf etwas anderes ändern.

Andere Tipps

Mit dem abc Modul . Insbesondere stellen Sie Ihren metaclass auf ABCMeta der Basisklasse und verwenden Sie die @abstractmethod Dekorateur auf cleanup Methode.

Die Debatte darüber, ob dies „pythonic“ ist gespalten. PEP 3119 , die den Standard beschreibt, sind einige der Vor-und Nachteile ( aber offensichtlich begünstigt ABCs). Das machte es in der Standard-Bibliothek, die eine ziemlich gute Anzeichen dafür, dass viele Menschen ist es unter Umständen sinnvoll erachten. In Ihrem Fall, ich denke, es ist angemessen.

Wenn Sie, dass die Bereinigung Verfahren sicherstellen wollen, implementiert ist, können Sie mit dem @abc.virtualmethod Dekorateur wickeln. Dies wird einen Fehler bei der Instanziierung eines Objekts verursacht, die die virtualmethod nicht außer Kraft gesetzt hat. Dies erfordert auch, dass Sie Ihre Klasse abc.ABCMeta machen __metaclass__.

Siehe abc Modul für weitere Informationen und einige Beispiele.

Dies ist nicht allgemein üblich ist: In der Regel gibt es nur Dokumente zu dem Effekt, dass Implementierer die gegebenen Methode außer Kraft setzen muß. Dies kann jedoch zu der Neuheit des abc Modul mehr fällig (neu in Python 2.6) als ein wahrgenommen unpythonicness diesen Ansatz.

Warum nicht die cleanup Methode hat gerade ein NotImplementedError erhöhen, wenn sie aufgerufen wird? Wenn sie Ihre Kinder Klassen arbeiten wollen müssen sie eine Art der Umsetzung in Kraft gesetzt werden.

Obwohl ich es nie persönlich in Anspruch genommen habe, habe ich viele Verweise auf

scroll top