Entonces, estoy jugando con decoradores en Python 2.6, y tengo algunos problemas para 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 significaba era tratar x
como una propiedad, pero llamar a estas funciones en get y set. Entonces, encendí IDLE y lo comprobé:
>>> 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 esperaba, ya que llamo al getter, y no hay un valor predeterminado, y falla. OK, bien, lo entiendo. Sin embargo, la llamada a asignar t.x = 5
parece crear una nueva propiedad x
, ¡y ahora el captador no funciona!
¿Qué me estoy perdiendo?
Respuestas:
Parece que está utilizando clases clásicas de estilo antiguo en python 2. Para que las propiedades funcionen correctamente, debe utilizar clases de estilo nuevo (en python 2 debe heredar de
object
). Simplemente declara tu clase comoMyClass(object)
:Funciona:
Otro detalle que puede causar problemas es que ambos métodos necesitan el mismo nombre para que la propiedad funcione. Si define el setter con un nombre diferente como este, no funcionará :
Y una cosa más que no es completamente fácil de detectar al principio, es el orden: el captador debe definirse primero . Si define primero el setter, obtendrá un
name 'x' is not defined
error.fuente
Solo una nota para otras personas que tropiezan aquí buscando esta excepción: ambas funciones deben tener el mismo nombre. Nombrar los métodos de la siguiente manera dará como resultado una excepción:
En su lugar, dale a ambos métodos el mismo nombre
También es importante tener en cuenta que el orden de la declaración es importante. El captador debe definirse antes que el definidor en el archivo o de lo contrario obtendrá un
NameError: name 'x' is not defined
fuente
NameError: name 'x' is not defined
excepción.Debes usar clases de estilo nuevo que haces derivando tu clase del objeto:
Entonces debería funcionar.
fuente
En caso de que alguien venga de google, además de las respuestas anteriores, me gustaría agregar que esto requiere una atención cuidadosa al invocar al setter desde el
__init__
método de su clase basado en esta respuesta Específicamente:fuente
__init__
método, sino de cualquier otro método de la clase.