ProgramaciónIngeniero de Software

¿Cómo funcionan las propiedades de las clases (class properties) en Python? ¿Cuál es la diferencia entre property y los atributos normales, cómo implementar una propiedad calculada, por qué es importante prestar atención a las funciones de control getter/setter?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

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:

  • Las propiedades ocultan cálculos o verificaciones detrás de un acceso normal al atributo.
  • property admite getter, setter, deleter.
  • El uso de property no requiere cambiar el código del usuario al cambiar la implementación.

Preguntas capciosas.

¿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.

Errores típicos y antipatrón

  • No usar atributos protegidos (_attr) o privados (__attr) en el backend de property — se puede lograr un bucle al referirse recursivamente a self.attr.
  • Uso de property sin necesidad (donde no hay cálculos o control).
  • Falta de validación en el setter, lo que lleva a romper los invariantes de la clase.

Ejemplo de la vida real

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.