En la lección anterior un objeto solo almacenaba atributos. Ahora vamos a colocar junto a esos datos las acciones que les pertenecen.
Un método expresa una acción. Una property permite consultar información como un atributo aunque se calcule mediante código.
Clasificar algo como estado, acción o dato derivado y elegir método o property según esa función.
Un método recibe la instancia y puede cambiar su estado
class Producto:
def __init__(self, nombre, stock):
self.nombre = nombre
self.stock = stock
def vender(self, unidades):
self.stock -= unidades
producto = Producto("Teclado", 10)
producto.vender(3)
print(producto.stock)vender() pertenece a Producto porque modifica una regla relacionada con un producto concreto. Al llamar producto.vender(3), self es ese objeto.
Un buen método evita repartir la misma regla por todo el programa
Sin vender(), distintos lugares podrían modificar stock cada uno a su manera. Al concentrar la operación en un método, sabes dónde cambiar la regla si mañana decides impedir ventas con stock insuficiente.
Pregunta de diseño sencilla: «¿esta acción depende de los datos de una instancia y tiene sentido pedirle al propio objeto que la realice?». Si sí, probablemente encaja como método.
Una property parece un atributo, pero puede calcular el valor al pedirlo
class Producto:
def __init__(self, precio):
self.precio = precio
@property
def precio_con_iva(self):
return self.precio * 1.21
producto = Producto(100)
print(producto.precio_con_iva)Observa la llamada: no escribes paréntesis en precio_con_iva. Desde fuera se consulta como un atributo.
Esto evita guardar dos datos que podrían desincronizarse. Si cambia precio, la property calcula el valor actualizado la próxima vez que se consulta.
No uses @property solo para evitar paréntesis
Una property funciona bien para una consulta que conceptualmente parece un dato del objeto y es rápida de calcular. Una operación pesada, con efectos secundarios o que claramente representa una acción suele ser mejor como método.
producto.precio_con_iva suena a información. producto.enviar_factura() suena a acción. Esa diferencia lingüística es una buena brújula.
Clasifica antes de elegir sintaxis
stock: dato que la instancia guarda.
vender(3): cambia el estado → método.
disponible: se calcula desde stock → puede ser property.
Parte A · método que cambia estado
Completa el método para restar las unidades vendidas al stock de la instancia.
7
La salida aparecerá aquí.
Necesito una pista
- El nuevo stock depende del stock actual y de
unidades.
Ver una solución razonada
class Producto:
def __init__(self, stock):
self.stock = stock
def vender(self, unidades):
self.stock = self.stock - unidades
producto = Producto(10)
producto.vender(3)
print(producto.stock)Parte B · property para un dato derivado
Añade una property disponible que calcule si queda stock. No guardes un segundo atributo que pueda desincronizarse.
True
La salida aparecerá aquí.
Necesito una pista
- Escribe
@propertysobre un método sin parámetros adicionales. - Devuelve
self.stock > 0.
Ver una solución razonada
class Producto:
def __init__(self, stock):
self.stock = stock
@property
def disponible(self):
return self.stock > 0
producto = Producto(2)
print(producto.disponible)Una property no debería esconder una sorpresa
Si al leer usuario.nombre_completo la aplicación realiza una petición de red, modifica un archivo o tarda varios segundos, la interfaz resulta engañosa: parece una consulta simple pero provoca una acción costosa.
Reserva las properties para información que se sienta natural al «leer» el objeto.
Recupera lo anterior · minuto 6
Un proyecto importa una clase Producto desde otro módulo. Cada producto guarda stock y ofrece una acción vender(). Señala origen del nombre, estado y acción.
Comprobar
El import indica de qué módulo viene Producto; stock es estado de cada instancia; vender() es un método que modifica ese estado.
Cierra este bloque distinguiendo datos, acciones y datos calculados
self.stockes estado almacenado en la instancia.vender()es una acción que puede modificar ese estado.precio_con_ivapuede ser una property si se deriva de otros atributos.
Si puedes decidir razonadamente si algo debería ser atributo, método o property, ya tienes una base mucho más útil que memorizar decoradores.