with tutorial framework espaƱol djangoproject desde con cero applications python

python - framework - tutorial django



''No se puede establecer el atributo'' con propiedades de nuevo estilo en Python (4)

Estoy tratando de usar la declaración de propiedades de nuevo estilo:

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

y ver lo siguiente en la consola:

pydev debugger: starting getting 0 File "/test.py", line 55, in <module> c.x = 10 AttributeError: can''t set attribute

¿Qué estoy haciendo mal? PD: La declaración de estilo antiguo funciona bien.


Cuando llama a @ x.setter, @ x.getter o @ x.deleter, está creando un nuevo objeto de propiedad y le da el nombre de la función que está decorando. Entonces, lo que realmente importa es que la última vez que use un decorador @ x. * Er en la definición de clase, tiene el nombre que realmente desea usar. Pero como esto dejaría su espacio de nombres de clase contaminado con versiones incompletas de la propiedad que desea usar, es mejor usar el mismo nombre para limpiarlos.


El método setter debe tener el mismo nombre que el getter. No te preocupes, el decorador sabe cómo diferenciarlos.

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


Si no quieres la ranura de nombre _x extra, aquí hay un pequeño truco complejo que puedes hacer:
(probado con 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 >>>


La documentación dice lo siguiente sobre el uso de la forma de decorador de la property :

Asegúrese de dar a las funciones adicionales el mismo nombre que la propiedad original (x en este caso).

No tengo idea de por qué esto es así, ya que si utiliza la property como función para devolver un atributo, los métodos pueden llamarse como desee.

Entonces necesitas cambiar tu código a lo siguiente:

@x.setter def x(self, value): ''setting'' self._x = value