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