Sollte ich einen Metaklas, einen Klassendekorator verwenden oder die __New__ -Methode überschreiben?
-
21-09-2019 - |
Frage
Hier ist mein Problem. Ich möchte, dass die folgende Klasse eine Reihe von Eigenschaftsattributen hat. Ich könnte sie entweder alle wie schreiben wie foo
und bar
, oder basierend auf einigen anderen Beispielen, die ich gesehen habe, sieht es so aus, als könnte ich einen Klassendekorator, einen Metaklas verwenden oder das überschreiben __new__
Methode zum automatischen Einstellen der Eigenschaften. Ich bin mir einfach nicht sicher, wie der "richtige" Weg es wäre.
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')
Lösung
Magie ist schlecht. Es macht Ihren Code schwerer zu verstehen und zu warten. Sie brauchen praktisch nie Metaklasse oder __new__
.
Es sieht so aus, als könnte Ihr Anwendungsfall mit ziemlich einfachem Code implementiert werden (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)
Andere Tipps
Ein Metaclass's __new__
wird nicht der __new__
Für die Klasse, die Sie erstellen - es wird verwendet, um die Klasse selbst zu machen. Das Aktuelles Klassenobjekt wird durch die Metaklasse zurückgegeben. Eine neue Instanz einer Klasse wird von zurückgegeben __new__
.
Betrachten Sie den folgenden (verrückten) 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 habe eine Funktion anstelle einer Klasse als Metaklas verwendet. Jeder Anruf kann als Metaklas verwendet werden, aber viele Menschen entscheiden sich dafür, ihre als Klassen zu korrigieren, von denen er erben type
mit neu überschrieben. Die Unterschiede zwischen einer Funktion sind subtil.)
Es gibt aus
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, was Metaklasse ist? sind?
Du wirst sehr selten Müssen eine eigene Metaklasse definieren.
Metaclass wird verwendet, wenn eine neue Klasse - nicht Instanz - erstellt wird. Auf diese Weise können Sie beispielsweise Klassen registrieren (Django macht es und verwendet es beispielsweise, um Tabellen in der Datenbank zu erstellen). Seit class
ist eine Anweisung, die Sie als Dekorateurin für eine Klasse betrachten können.