property define decorators and python decorator new-style-class

define - ¿Por qué @ foo.setter en Python no funciona para mí?



python property decorator (4)

En caso de que alguien venga desde google, además de las respuestas anteriores, me gustaría añadir que esto requiere una atención cuidadosa al invocar al setter desde el método __init__ de su clase basado en esta respuesta específicamente:

class testDec(object): def __init__(self, value): print ''We are in __init__'' self.x = value # Will call the setter. Note just x here #self._x = value # Will not call the setter @property def x(self): print ''called getter'' return self._x # Note the _x here @x.setter def x(self, value): print ''called setter'' self._x = value # Note the _x here t = testDec(17) print t.x Output: We are in __init__ called setter called getter 17

Entonces, estoy jugando con decoradores en Python 2.6, y estoy teniendo problemas para hacer que funcionen. Aquí está mi archivo de clase:

class testDec: @property def x(self): print ''called getter'' return self._x @x.setter def x(self, value): print ''called setter'' self._x = value

Lo que pensé que esto significaba era tratar x como una propiedad, pero llamar a estas funciones en get y set. Entonces, encendí IDLE y lo revisé:

>>> from testDec import testDec from testDec import testDec >>> t = testDec() t = testDec() >>> t.x t.x called getter Traceback (most recent call last): File "<stdin>", line 1, in <module> File "testDec.py", line 18, in x return self._x AttributeError: testDec instance has no attribute ''_x'' >>> t.x = 5 t.x = 5 >>> t.x t.x 5

Claramente, la primera llamada funciona como se espera, ya que llamo al getter, y no hay un valor predeterminado, y falla. OK, bien, lo entiendo. Sin embargo, la llamada para asignar tx = 5 parece crear una nueva propiedad x , ¡y ahora el getter no funciona!

¿Qué me estoy perdiendo?


Necesita usar clases de estilo nuevo que hace derivando su clase de un objeto:

class testDec(object): ....

Entonces debería funcionar.


Parece que estás usando clases clásicas de estilo antiguo . Para que las properties funcionen correctamente, debe usar clases de estilo nuevo ( heredar del object ). Simplemente declare su clase como MyClass(object) :

class testDec(object): @property def x(self): print ''called getter'' return self._x @x.setter def x(self, value): print ''called setter'' self._x = value

Funciona:

>>> k = testDec() >>> k.x called getter Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/devel/class_test.py", line 6, in x return self._x AttributeError: ''testDec'' object has no attribute ''_x'' >>> k.x = 5 called setter >>> k.x called getter 5 >>>


Solo una nota para otras personas que tropiecen aquí en busca de esta excepción: ambas funciones deben tener el mismo nombre. Nombrar los métodos de la siguiente manera resultará en una excepción:

@property def x(self): pass @x.setter def x_setter(self, value): pass

En lugar de dar a ambos métodos el mismo nombre

@property def x(self): pass @x.setter def x(self, value): pass

También es importante tener en cuenta que el orden de la declaración importa. El getter debe definirse antes que el setter en el archivo o de lo contrario obtendrá un NameError: name ''x'' is not defined