@property
1. Qué es property? #
En Python, property es una función que permite controlar el acceso a los atributos de una clase mediante el uso de métodos en lugar de acceder directamente a los atributos. Esto te permite definir comportamiento personalizado cuando obtienes, estableces o eliminas un valor de un atributo. Usar property es útil para encapsular datos, permitiendo cambiar la implementación interna de una clase sin cambiar su interfaz pública.
2. Cómo funciona property? #
La función property te permite definir tres cosas:
- Getter: Un método para obtener el valor del atributo.
- Setter: Un método para establecer el valor del atributo.
- Deleter (opcional): Un método para eliminar el atributo.
- Docstring (opcional): Un string para documentar el atributo.
3. Ejemplo básico usando property #
Vamos a ver cómo funciona property con un ejemplo sencillo:
1class Persona: 2 def __init__(self, nombre): 3 self._nombre = nombre # Atributo "privado" 4 5 @property 6 def nombre(self): 7 return self._nombre 8 9 @nombre.setter 10 def nombre(self, nuevo_nombre): 11 if isinstance(nuevo_nombre, str) and nuevo_nombre: 12 self._nombre = nuevo_nombre 13 else: 14 raise ValueError("El nombre debe ser una cadena no vacía.") 15 16# Crear una instancia de la clase Persona 17persona1 = Persona("Ana") 18 19# Usar el getter para obtener el nombre 20print(persona1.nombre) # Resultado: Ana 21 22# Usar el setter para cambiar el nombre 23persona1.nombre = "Carlos" 24print(persona1.nombre) # Resultado: Carlos 25 26# Intentar establecer un nombre no válido (esto lanzará una excepción) 27# persona1.nombre = "" # Descomenta esta línea para ver el errorSalida de consola Ana Carlos
- ¿Qué hace este código?:
- Define una clase
Personacon un atributo "privado"_nombre. - El método
nombredecorado con@propertyactúa como un getter, permitiendo acceder al atributo_nombrede manera controlada. - El método
nombredecorado con@nombre.setteractúa como un setter, permitiendo establecer el valor de_nombrecon validación. - Intentar establecer un nombre no válido (como una cadena vacía) lanzará una excepción
ValueError.
- Define una clase
4. Ejemplo con deleter #
Ahora, veamos cómo podemos usar un deleter con property para eliminar un atributo:
1class Persona: 2 def __init__(self, nombre): 3 self._nombre = nombre 4 5 @property 6 def nombre(self): 7 return self._nombre 8 9 @nombre.setter 10 def nombre(self, nuevo_nombre): 11 if isinstance(nuevo_nombre, str) and nuevo_nombre: 12 self._nombre = nuevo_nombre 13 else: 14 raise ValueError("El nombre debe ser una cadena no vacía.") 15 16 @nombre.deleter 17 def nombre(self): 18 print(f"Eliminando el nombre '{self._nombre}'") 19 del self._nombre 20 21# Crear una instancia de la clase Persona 22persona1 = Persona("Ana") 23 24# Eliminar el nombre usando el deleter 25del persona1.nombre 26 27# Intentar acceder al atributo después de eliminarlo (esto lanzará un AttributeError) 28# print(persona1.nombre) # Descomenta esta línea para ver el errorSalida de consola Eliminando el nombre 'Ana'
- ¿Qué hace este código?:
- Añade un deleter para el atributo
nombre, que permite eliminar el atributo_nombre. - Cuando llamas a
del persona1.nombre, se ejecuta el métodonombre.deleter. - Intentar acceder a
persona1.nombredespués de eliminarlo lanzará unAttributeError.
- Añade un deleter para el atributo
5. Por qué usar property? #
- Encapsulación: Permite controlar cómo se accede y modifica un atributo, encapsulando la lógica de validación y otros comportamientos.
- Flexibilidad: Te permite cambiar la implementación interna de cómo se almacena un atributo sin cambiar cómo se usa desde fuera de la clase.
- Simplicidad: Hace que el código que usa la clase sea más limpio, ya que puedes acceder a los atributos como si fueran públicos, mientras en realidad están gestionados por métodos.
Resumen del tema
Conceptos clave #
- Decorador
@property(Getter): transforma un método en un atributo de sólo lectura accesible sin paréntesisobjeto.propiedad. - Decorador
@propiedad.setter: define la lógica de asignación y validación de tipos o rangos cuando se ejecutaobjeto.propiedad = valor. - Decorador
@propiedad.deleter: intercepta la eliminación del atributo al invocardel objeto.propiedad. - Encapsulación Pitónica: permite refactorizar atributos públicos existentes agregando validaciones sin romper la API externa consumida por los clientes de la clase.
Qué debes recordar #
Usa @property y @propiedad.setter para proteger atributos con lógica de validación manteniendo la sintaxis limpia de acceso directo a atributos.