Las propiedades (property) en Python surgieron como una forma elegante de implementar la encapsulación de atributos, similar a los getters y setters de otros lenguajes (Java/C++), pero sin la necesidad de llamar métodos explícitamente. Antes de property, se tenía que implementar el acceso a las variables a través de métodos explícitos get/set, lo que complicaba y ensuciaba la interfaz de la clase.
El problema es que el usuario de la clase debe tener una interfaz transparente para trabajar con los atributos (usando la notación de punto obj.x), mientras que internamente se puede controlar la lógica de cálculo, verificación, almacenamiento en caché o validación de valores. Sin property, al cambiar la implementación interna, es necesario cambiar todas las llamadas, lo que genera muchos errores y disminuye la extensibilidad.
La solución — el decorador @property convierte un método en un atributo y, a la vez, oculta la lógica de cálculo, verificación o carga perezosa dentro de los métodos, sin cambiar la interfaz externa de la clase. El getter se implementa solo para lectura, con .setter se organiza la escritura, y .deleter — la eliminación.
Ejemplo de código:
class Rectangle: def __init__(self, width, height): self._width = width self._height = height @property def area(self): # 'area' ahora se puede leer como un atributo return self._width * self._height @property def width(self): return self._width @width.setter def width(self, value): # se llama automáticamente al asignar rect.width = ... assert value > 0, "El ancho debe ser positivo" self._width = value rect = Rectangle(3, 4) print(rect.area) # 12 rect.width = 10 print(rect.area) # 40
Características clave:
¿Puede property trabajar con métodos de clase o métodos estáticos?
No. property solo hace propiedades a nivel de instancia (de instancias). Para a nivel de clase se deben usar descriptores especiales o @classmethod-property (implementado manualmente).
Si se declara una property solo con getter sin setter, ¿se podrá escribir en el atributo?
No. Esa property es de solo lectura; intentar asignar un valor generará un AttributeError.
¿Qué sucede si se genera una excepción dentro del setter (por ejemplo, un assert)?
La excepción se elevará hacia afuera, la asignación no se realizará y el valor del atributo permanecerá igual. Esto se utiliza a menudo para la validación.
Caso negativo: Atributos públicos de la clase, modificación de ellos sin control.
Ventajas: rápido, simple.
Desventajas: no se puede cambiar la lógica interna sin reescribir el código del cliente, pueden ocurrir estados inconsistentes.
Caso positivo: Encapsulación a través de property, lógica en getter/setter, comprobaciones estrictas.
Ventajas: flexibilidad, control, transparencia, evolución segura de la API.
Desventajas: un poco más de código, complicación ligera al depurar.