Ich habe Python-Eigenschaften erfolgreich verwendet, sehe aber nicht, wie sie funktionieren könnten. Wenn ich eine Eigenschaft außerhalb einer Klasse dereferenziere, erhalte ich nur ein Objekt vom Typ property
:
@property
def hello(): return "Hello, world!"
hello # <property object at 0x9870a8>
Aber wenn ich eine Eigenschaft in eine Klasse einbaue, ist das Verhalten ganz anders:
class Foo(object):
@property
def hello(self): return "Hello, world!"
Foo().hello # 'Hello, world!'
Ich habe bemerkt, dass ungebunden Foo.hello
immer noch das property
Objekt ist, also muss Klasseninstanziierung die Magie sein, aber welche Magie ist das?
python
properties
Fred Foo
quelle
quelle
max recursion depth exceeded
... hahaaAntworten:
Wie andere angemerkt haben, verwenden sie eine Sprachfunktion, die als Deskriptoren bezeichnet wird.
Der Grund, warum das eigentliche Eigenschaftsobjekt zurückgegeben wird, wenn Sie über eine Klasse darauf zugreifen,
Foo.hello
liegt darin, wie die Eigenschaft die__get__(self, instance, owner)
spezielle Methode implementiert :owner
ist die Klasse dieser Instanz.instance
ist None und wird nurowner
übergeben. Dasproperty
Objekt erkennt dies und kehrt zurückself
.Neben dem Deskriptor-Howto finden Sie auch die Dokumentation zum Implementieren von Deskriptoren und zum Aufrufen von Deskriptoren im Sprachhandbuch .
quelle
Damit @properties ordnungsgemäß funktioniert, muss die Klasse eine Unterklasse von Objekten sein . Wenn die Klasse keine Unterklasse von Objekten ist, erstellt sie beim ersten Versuch, auf den Setter zuzugreifen, tatsächlich ein neues Attribut mit dem kürzeren Namen, anstatt über den Setter zuzugreifen.
Folgendes funktioniert nicht richtig.
class C(): # <-- Notice that object is missing def __init__(self): self._x = None @property def x(self): print 'getting value of x' return self._x @x.setter def x(self, x): print 'setting value of x' self._x = x >>> c = C() >>> c.x = 1 >>> print c.x, c._x 1 0
Folgendes wird korrekt funktionieren
class C(object): def __init__(self): self._x = None @property def x(self): print 'getting value of x' return self._x @x.setter def x(self, x): print 'setting value of x' self._x = x >>> c = C() >>> c.x = 1 setting value of x >>> print c.x, c._x getting value of x 1 1
quelle
Eigenschaften sind Deskriptoren , und Deskriptoren verhalten sich besonders, wenn sie Mitglied einer Klasseninstanz sind. Kurz gesagt, wenn
a
es sich um eine Instanz vom TypA
undA.foo
einen Deskriptor handelt,a.foo
entspricht diesA.foo.__get__(a)
.quelle
__get__()
falsch ist. Es hat zwei Argumente (zusätzlich zu Selbst). Ansonsten gut erklärt.Das
property
Objekt implementiert lediglich das Deskriptorprotokoll: http://docs.python.org/howto/descriptor.htmlquelle