2010-03-23 4 views
5

Hier ist mein Problem. Ich möchte, dass die folgende Klasse eine Reihe von Eigenschaftenattributen aufweist. Ich könnte sie alle wie foo und bar schreiben, oder basierend auf einigen anderen Beispielen, die ich gesehen habe, sieht es so aus, als könnte ich einen Klassen-Dekorator oder eine Metaklasse verwenden oder die __new__-Methode überschreiben, um die Eigenschaften automatisch festzulegen. Ich bin mir nur nicht sicher, was der "richtige" Weg wäre, es zu tun.Soll ich eine Metaklasse oder einen Klassen-Decorator verwenden oder die Methode __new__ überschreiben?

class Test(object): 
    def calculate_attr(self, attr): 
     # do calculaty stuff 
     return attr 

    @property 
    def foo(self): 
     return self.calculate_attr('foo') 

    @property 
    def bar(self): 
     return self.calculate_attr('bar') 
+2

Im Zweifelsfall geht immer mit einfacher und offensichtlich. Wenn * Sie * es nicht leicht herausfinden können, können auch keine Dummies (wie ich), die aufgefordert werden, Ihren Code zu pflegen. –

+0

Wenn Sie die Art Ihrer Fragen ändern, ist es normalerweise am besten, nur eine neue zu öffnen. –

Antwort

4

Magie ist schlecht. Es macht Ihren Code schwieriger zu verstehen und zu pflegen. Sie brauchen praktisch nie Metaklassen oder __new__.

Es sieht aus wie Ihr Anwendungsfall mit ziemlich einfach Code implementiert werden kann (mit nur einem kleinen Hauch von Magie):

class Test(object): 
    def calculate_attr(self, attr): 
     return something 

    def __getattr__(self, name): 
     return self.calculate_attr(name) 
+1

@Sie brauchen praktisch nie Metaklassen oder '__new__': Ich stimme überhaupt nicht zu. In meiner Firma hatten wir bereits zwei Gelegenheiten, als wir eine gute Motivation für den Einsatz von Metaklassen hatten. Zuerst wurde eine Abstraktionsschicht für eine benutzerdefinierte Datenbank erstellt, die wir verwendet hatten, und die andere erstellte ein eigenes Modellsystem für ldap. Ich kann nicht wirklich verstehen, wo kommt dieser Groll für Metaklassen her. Es ist ein einfaches Konzept zu erfassen und in bestimmten Situationen wirklich nützlich. – gruszczy

+1

@gruszczy, Metaklassen sind nicht schwer zu verstehen, sie sind eigentlich eine ziemlich einfache Idee, obwohl die Syntax und die Verwendung für sie in Python macht einige Leute Probleme haben. Sie sind jedoch fehleranfällig aufgrund der Art, wie sie sich ausbreiten und manchmal schwierig zu kombinieren sind. Es ist nicht automatisch möglich, dass eine Klasse zwei Metaklassen in ihrer Konstruktion verwendet, selbst wenn dies eine vollkommen vernünftige Operation ist. Dieses Problem wird durch die Tatsache verstärkt, dass Metaklassen häufig nicht als Teil der öffentlichen API eines Systems verfügbar gemacht werden. –

2

der A metaclass __new__ hat sich nicht die __new__ für die Klasse, die Sie verwendet Make-es ist die Klasse selbst zu machen. Das tatsächliche Klassenobjekt wird von der Metaklasse zurückgegeben. Eine neue Instanz einer Klasse wird von __new__ zurückgegeben.

Betrachten Sie die folgende (verrückt) Code:.

def MyMetaClass(name, bases, dict): 
    print "name", name 
    print "bases", bases 
    print "dict", dict 
    return 7 

class C('hello', 'world'): 
    __metaclass__ = MyMetaClass 

    foo = "bar" 

    def baz(self, qux): 
     pass 

print "C", C 

(ich eine Funktion statt einer Klasse, die als Metaklasse verwendet Alle abrufbaren als Metaklasse verwendet werden kann, aber viele Menschen wählen zu Recht ihre als Klassen dass vererben type mit neuen overrided. die Unterschiede zwischen dem, eine Funktion sind subtil.)

Es gibt

name C 
bases ('hello', 'world') 
dict {'baz': <function baz at 0x4034c844>, '__module__': '__main__', 'foo': 'bar', '__metaclass__': <function MyMetaClass at 0x40345c34>} 
C 7 

Hilft Ihnen das, besser zu verstehen, welche Metaklassen sind?

Sie werden sehr selten müssen eine eigene Metaklasse definieren.

+0

Sollte das nicht "tatsächliches Klassenobjekt" und nicht "eigentlich Klassenobjekt" sein? –

1

Metaklasse wird verwendet, wenn neue Klasse - keine Instanz - erstellt wird. Auf diese Weise können Sie beispielsweise Klassen registrieren (django macht es und verwendet es zum Beispiel, um Tabellen in der Datenbank zu erstellen). Seit class ist eine Anweisung, die Sie als Dekorator für eine Klasse denken können.

Verwandte Themen