Ich versuche, die Deklaration neuer Eigenschaften zu verwenden:
class C(object):
def __init__(self):
self._x = 0
@property
def x(self):
print 'getting'
return self._x
@x.setter
def set_x(self, value):
print 'setting'
self._x = value
if __name__ == '__main__':
c = C()
print c.x
c.x = 10
print c.x
und sehen Sie Folgendes in der Konsole:
pydev debugger: starting
getting
0
File "\test.py", line 55, in <module>
c.x = 10
AttributeError: can't set attribute
Was mache ich falsch? PS: Die Deklaration im alten Stil funktioniert einwandfrei.
'setting'
(eine Dokumentzeichenfolge)print 'setting'
(eine einfache Debugging-Anweisung) wird. Es ist sicherlich plausibel, dass die print-Anweisung beabsichtigt war, aber es gibt keinen Schaden oder Fehler in der Dokumentzeichenfolge und es hat keinerlei Auswirkungen auf die Frage.Antworten:
In der Dokumentation wird Folgendes zur Verwendung der Dekorationsform beschrieben
property
:Ich habe keine Ahnung, warum dies so ist, da
property
die Methoden aufgerufen werden können, wenn Sie als Funktion ein Attribut zurückgeben.Sie müssen Ihren Code also wie folgt ändern:
@x.setter def x(self, value): 'setting' self._x = value
quelle
def
Zeile) als Attributnamen zu verwenden. In OPs Fall, in dem er eine Methode namens aufgerufenset_x
und als Setter dekoriert hat, hat er tatsächlich ein einstellbares Attribut namensset_x
! Also, anstattc.x = 10
was er tun könnte, istc.set_x = 10
. Beachten Sie, dass der Name im Dekorateur keine Rolle spielt. Wenn er zwei Eigenschaften hättex
undy
, könnte er genauso gut ein Setter-Attribut verwenden@x.setter
oder@y.setter
esset_x
in ein Setter-Attribut verwandeln (das einen Wert zuweistself._x
).Die Setter-Methode muss denselben Namen wie der Getter haben. Keine Sorge, der Dekorateur weiß, wie man sie voneinander unterscheidet.
@x.setter def x(self, value): ...
quelle
Wenn Sie @ x.setter, @ x.getter oder @ x.deleter aufrufen, erstellen Sie ein neues Eigenschaftsobjekt und geben ihm den Namen der Funktion, die Sie dekorieren. Alles, was wirklich zählt, ist, dass das letzte Mal, wenn Sie einen @ x. * Er-Dekorator in der Klassendefinition verwenden, dieser den Namen hat, den Sie tatsächlich verwenden möchten. Da Ihr Klassennamensraum dadurch jedoch mit unvollständigen Versionen der Eigenschaft verschmutzt wird, die Sie verwenden möchten, verwenden Sie zum Bereinigen am besten denselben Namen.
quelle
Wenn Sie den zusätzlichen
_x
Namensschlitz nicht möchten , können Sie hier einen komplexen kleinen Trickausführen : (getestet mit Py34)
>>> class C(object): __slots__ = ['x'] # create a member_descriptor def __init__( self ): self.x = 0 # or use this if you don't want to call x_setter: #set_x( self, 0 ) >>> get_x = C.x.__get__ # member_descriptor getter >>> set_x = C.x.__set__ # member_descriptor setter >>> # define custom wrappers: >>> def x_getter( self ): print('getting') return get_x( self ) >>> def x_setter( self, value ): print('setting') set_x( self, value ) >>> C.x = property( x_getter, x_setter ) # replace the member_descriptor >>> c = C() setting >>> print(c.x) getting 0 >>> c.x = 10 setting >>>
quelle