Curso de Python / Controlar cambios en objetos con métodos y propiedades
Una propiedad permite acceder a un valor con la sintaxis de un atributo y ejecutar código al leerlo o asignarlo. En Python, property resulta útil para mantener una regla al actualizar un objeto, mientras que un método expresa una operación, como añadir un recargo.
Por qué validar también las actualizaciones
Comprobar un importe solo en __init__ no impide que una asignación posterior deje el objeto en un estado inválido. En la introducción a las clases se distinguía la construcción de los cambios posteriores. Aquí ambas rutas pasan por el mismo setter, el método que atiende la asignación a una propiedad.
El contrato del ejemplo acepta únicamente un entero no negativo. type(value) is int excluye los booleanos, que Python considera una subclase de int. Esta es una decisión del dominio: no todas las aplicaciones necesitan rechazar los mismos tipos ni utilizar la misma excepción.
Crear una propiedad con una regla común
Guarda el programa completo como properties.py y ejecútalo con python properties.py. No requiere instalaciones adicionales. El getter devuelve el importe y el setter lo valida antes de guardarlo en _amount.
class Expense:
def __init__(self, amount):
self.amount = amount
@property
def amount(self):
return self._amount
@amount.setter
def amount(self, value):
if type(value) is not int or value < 0:
raise ValueError("amount must be a nonnegative integer")
self._amount = value
def add_fee(self, fee):
self.amount = self.amount + fee
item = Expense(8000)
item.add_fee(500)
print(item.amount)
try:
item.amount = -1
except ValueError:
print("rejected")
print(item.amount)
El recargo eleva el importe a 8500. Después se rechaza la asignación negativa y el valor anterior permanece intacto:
8500
rejected
8500
self.amount = amount dentro del inicializador llama al setter. Del mismo modo, el cambio realizado por add_fee vuelve a pasar por esa comprobación. Así no necesitas repetir la validación básica en cada lugar que actualiza el importe.
Evitar recursión y falsas garantías
Dentro del setter, escribir de nuevo self.amount = value llamaría al mismo setter indefinidamente. Por eso la asignación final utiliza self._amount. El guion bajo inicial comunica que es un detalle interno; no crea una barrera de seguridad ni hace imposible el acceso desde otro código.
Es importante validar antes de modificar ese atributo interno: si llega un valor incorrecto, el objeto conserva su estado anterior. Una propiedad sin setter impide la asignación normal mediante ese nombre, pero no vuelve inmutables todos los objetos que pudiera contener.
Elegir entre atributo, propiedad y método
Usa un atributo sencillo cuando no exista una regla especial. Una propiedad encaja con una lectura o actualización que el lector espera que se comporte como acceso a un dato. Utiliza un método para operaciones con significado propio o con costes y efectos importantes. Evita ocultar peticiones de red o grandes lecturas de archivos detrás de una propiedad aparentemente trivial.
Prueba por separado las asignaciones True y 3.5, captura ValueError y comprueba que el importe sigue siendo 8500. Restaura el ejemplo después. Para decidir si un recargo negativo está permitido necesitas una regla adicional: validar el importe final no equivale a definir todas las condiciones del recargo. Estas pruebas pueden automatizarse con unittest.
La referencia oficial de property describe los accesores y sus decoradores. Mantener una interfaz clara ayuda a cambiar la representación interna sin obligar a los usuarios del objeto a conocerla.




