Propiedades
Vamos a ver en detalle cómo funcionan las propiedades en Python, cómo se define su nivel de visibilidad (pública, protegida, privada) y cómo se usan los getters y setters de forma manual y con el decorador @property
.
🧱 1. Visibilidad de atributos
Python no tiene modificadores de acceso como private
, public
, protected
(como en Java o C#), pero se puede seguir una convención de nombres:
Nivel de visibilidad | Sintaxis | Descripción |
---|---|---|
Pública | self.nombre |
Se puede acceder libremente desde fuera |
Protegida (convención) | self._nombre |
Sugiere que no se debe acceder desde fuera directamente |
Privada (name mangling) | self.__nombre |
El nombre se renombra internamente (_Clase__nombre ) para mayor seguridad |
🛠️ 2. Getters y Setters manuales
class Persona:
def __init__(self, nombre, edad):
self.__nombre = nombre # Atributo privado
self.__edad = edad
# Getter para nombre
def get_nombre(self):
return self.__nombre
# Setter para nombre
def set_nombre(self, nuevo_nombre):
if isinstance(nuevo_nombre, str) and nuevo_nombre.strip():
self.__nombre = nuevo_nombre
else:
print("Nombre inválido")
persona = Persona("Lucía", 25)
print(persona.get_nombre()) # Lucía
persona.set_nombre("Ana")
print(persona.get_nombre()) # Ana
✅ 3. Getters y Setters con @property
(la forma “pythónica” recomendada)
class Producto:
def __init__(self, precio):
self.__precio = precio
@property
def precio(self):
print("Obteniendo precio...")
return self.__precio
@precio.setter
def precio(self, nuevo_precio):
print("Estableciendo nuevo precio...")
if nuevo_precio >= 0:
self.__precio = nuevo_precio
else:
print("Precio no válido")
# Usar la clase
p = Producto(100)
print(p.precio) # Llama al getter
p.precio = 150 # Llama al setter
print(p.precio)
🧠 ¿Qué pasa aquí?
@property
convierte el métodoprecio()
en una propiedad: puedes acceder como si fuera un atributo (p.precio
), pero detrás hay lógica.@precio.setter
define qué pasa cuando alguien hacep.precio = algo
.
🔒 4. Ejemplo completo con niveles de visibilidad y validación
class CuentaBancaria:
def __init__(self, titular, saldo):
self._titular = titular # protegido
self.__saldo = saldo # privado
@property
def saldo(self):
return self.__saldo
@saldo.setter
def saldo(self, cantidad):
if cantidad >= 0:
self.__saldo = cantidad
else:
print("No se puede asignar un saldo negativo.")
def mostrar_info(self):
print(f"Titular: {self._titular}, Saldo: {self.__saldo}")
cuenta = CuentaBancaria("Mario", 500)
cuenta.mostrar_info()
cuenta.saldo = 1000 # usa el setter
print(cuenta.saldo) # usa el getter
🧾 Resumen
Concepto | ¿Qué hace? |
---|---|
@property |
Define un getter |
@<nombre>.setter |
Define un setter para ese atributo |
__atributo |
Atributo privado (name mangling: _Clase__atributo ) |
_atributo |
Atributo protegido (por convención, no real restricción) |
atributo |
Atributo público |