Estoy interesado en cómo usarlo @property
en Python. He leído los documentos de Python y el ejemplo allí, en mi opinión, es solo un código de juguete:
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
No sé qué beneficio (s) puedo obtener al envolver el _x
relleno con el decorador de propiedades. ¿Por qué no simplemente implementar como:
class C(object):
def __init__(self):
self.x = None
Creo que la característica de propiedad podría ser útil en algunas situaciones. ¿Pero cuando? ¿Podría alguien darme algunos ejemplos del mundo real?
Gracias.
python
oop
properties
python-decorators
xiao 啸
fuente
fuente
Respuestas:
Otros ejemplos serían la validación / filtrado de los atributos establecidos (forzándolos a estar dentro de límites o aceptables) y la evaluación diferida de términos complejos o que cambian rápidamente.
Cálculo complejo oculto detrás de un atributo:
Validación:
fuente
Un caso de uso simple será establecer un atributo de instancia de solo lectura, ya que sabe que llevar un nombre de variable con un guión bajo
_x
en Python generalmente significa que es privado (uso interno), pero a veces queremos poder leer el atributo de instancia y no escribir es así que se puede utilizarproperty
para esto:fuente
c._x
, si el usuario lo desea. Python en realidad no tiene atributos privados reales.Eche un vistazo a este artículo para un uso muy práctico. En resumen, explica cómo en Python generalmente puede deshacerse del método getter / setter explícito, ya que si llega a necesitarlos en algún momento, puede usarlos
property
para una implementación perfecta.fuente
Una cosa para la que lo he usado es el almacenamiento en caché de valores lentos para buscar, pero inmutables, almacenados en una base de datos. Esto se generaliza a cualquier situación en la que sus atributos requieran cómputo u otra operación larga (por ejemplo, verificación de la base de datos, comunicación de red) que solo desea hacer a pedido.
Esto fue en una aplicación web donde cualquier vista de página dada solo podría necesitar un atributo particular de este tipo, pero los objetos subyacentes podrían tener varios de estos atributos: inicializarlos todos en la construcción sería un desperdicio, y las propiedades me permiten ser flexible en lo que los atributos son perezosos y cuáles no.
fuente
@cached_property
para esto?Leyendo las respuestas y comentarios, el tema principal parece ser que las respuestas parecen estar perdiendo un ejemplo simple pero útil. He incluido uno muy simple aquí que demuestra el uso simple del
@property
decorador. Es una clase que permite al usuario especificar y obtener mediciones de distancia utilizando una variedad de unidades diferentes, es decir,in_feet
oin_metres
.Uso:
fuente
La propiedad es solo una abstracción en torno a un campo que le brinda más control sobre las formas en que un campo específico puede ser manipulado y hacer cálculos de middleware. Pocos de los usos que vienen a la mente son la validación y la inicialización previa y la restricción de acceso
fuente
Sí, para el ejemplo original publicado, la propiedad funcionará exactamente igual que simplemente tener una variable de instancia 'x'.
Esto es lo mejor de las propiedades de Python. ¡Desde el exterior, funcionan exactamente como variables de instancia! Lo que le permite usar variables de instancia fuera de la clase.
Esto significa que su primer ejemplo podría usar una variable de instancia. Si las cosas cambiaron, y luego decide cambiar su implementación y una propiedad es útil, la interfaz de la propiedad seguirá siendo la misma desde el código fuera de la clase. Un cambio de variable de instancia a propiedad no tiene impacto en el código fuera de la clase.
Muchos otros lenguajes y cursos de programación darán instrucciones de que un programador nunca debe exponer variables de instancia, y en su lugar usar 'getters' y 'setters' para acceder a cualquier valor desde fuera de la clase, incluso el caso simple como se cita en la pregunta.
Código fuera de la clase con muchos idiomas (por ejemplo, Java)
Y al implementar la clase, hay muchos 'captadores' y 'establecedores' que hacen exactamente como su primer ejemplo: replicar una variable de instancia simple. Estos captadores y establecedores son necesarios porque si la implementación de la clase cambia, todo el código fuera de la clase deberá cambiar. Pero las propiedades de Python permiten que el código fuera de la clase sea el mismo que con las variables de instancia. Por lo tanto, no es necesario cambiar el código fuera de la clase si agrega una propiedad o si tiene una variable de instancia simple. Entonces, a diferencia de la mayoría de los lenguajes orientados a objetos, para su ejemplo simple, puede usar la variable de instancia en lugar de 'getters' y 'setters' que realmente no son necesarios, tenga la certeza de que si cambia a una propiedad en el futuro, el código usa Tu clase no necesita cambiar.
Esto significa que solo necesita crear propiedades si hay un comportamiento complejo, y para el caso simple muy común en el que, como se describe en la pregunta, una variable de instancia simple es todo lo que se necesita, simplemente puede usar la variable de instancia.
fuente
Otra buena característica de las propiedades sobre el uso de setters y getters es que le permiten continuar usando operadores OP = (por ejemplo, + =, - =, * = etc.) en sus atributos mientras conserva cualquier validación, control de acceso, almacenamiento en caché, etc. los acomodadores y captadores proporcionarían.
por ejemplo, si escribiste la clase
Person
con un settersetage(newage)
y un gettergetage()
, para aumentar la edad tendrías que escribir:pero si hiciste
age
una propiedad, podrías escribir el limpiador mucho más:fuente
La respuesta corta a su pregunta es que, en su ejemplo, no hay beneficio. Probablemente debería usar el formulario que no involucra propiedades.
La razón por la que existen las propiedades es que si su código cambia en el futuro y de repente necesita hacer más con sus datos: valores de caché, proteger el acceso, consultar algún recurso externo ... lo que sea, puede modificar fácilmente su clase para agregar captadores y configuradores para los datos sin cambiar la interfaz, por lo que no tiene que buscar en todas partes en su código donde se accede a esos datos y cambiar eso también.
fuente
Algo que muchos no notan al principio es que puede crear sus propias subclases de propiedad. Esto me ha resultado muy útil para exponer atributos de objetos de solo lectura o atributos que puede leer y escribir pero no eliminar. También es una excelente manera de ajustar la funcionalidad, como el seguimiento de modificaciones a los campos de objetos.
fuente
attr = reader('_attr')
línea o alguna forma de verificación previaattr = if self.__isValid(value): reader('_attr')
. Sugerencias?attr = reader('_attr')
aattr = accessor('_attr')
. Gracias