El encapsulamiento consiste en ocultar los detalles internos de una clase y exponer solo lo necesario.
Su objetivo es:
Proteger los datos
Evitar modificaciones indebidas
Controlar el acceso
Mantener la integridad del objeto
Python no tiene privacidad estricta como Java o C#, pero usa convenciones y mecanismos que cumplen la misma función.
1. Atributos públicos, protegidos y privados
Público
Accesible desde cualquier parte.
self.nombre
Protegido (convención)
Indica que no debería tocarse desde fuera.
self._saldo
Privado (name mangling)
Python renombra internamente el atributo para evitar accesos accidentales.
self.__saldo
2. Ejemplo básico de encapsulamiento
class Cuenta:
def __init__(self, titular, saldo):
self.titular = titular # público
self.__saldo = saldo # privado
def ver_saldo(self):
return self.__saldo
def ingresar(self, cantidad):
if cantidad > 0:
self.__saldo += cantidad
def retirar(self, cantidad):
if 0 < cantidad <= self.__saldo:
self.__saldo -= cantidad
3. Getters y Setters (propiedades)
Python permite crear propiedades con @property, una forma elegante de controlar el acceso.
class Persona:
def __init__(self, nombre):
self._nombre = nombre
@property
def nombre(self):
return self._nombre
@nombre.setter
def nombre(self, nuevo):
if len(nuevo) < 2:
raise ValueError("El nombre es demasiado corto")
self._nombre = nuevo
Uso:
p = Persona("Ana")
print(p.nombre)
p.nombre = "Luis"
4. ¿Por qué usar encapsulamiento?
Evita estados inválidos
Permite validar datos antes de asignarlos
Facilita mantenimiento
Protege información sensible (contraseñas, saldos, etc.)
Permite cambiar la implementación interna sin romper el código externo
ACTIVIDAD PRÁCTICA: “Sistema de cuenta bancaria segura”
Objetivo: que tus alumnos practiquen atributos privados, getters/setters y validación.
Enunciado
Crea una clase CuentaBancaria con:
Atributos privados:
__titular__saldo__iban
Métodos:
depositar(cantidad)retirar(cantidad)ver_saldo()Propiedad
iban(solo lectura)Propiedad
titular(lectura y escritura con validación)
Requisitos:
No permitir saldo negativo
No permitir nombres vacíos
No permitir depósitos o retiradas negativas
Mostrar mensajes claros
Después:
Crea una cuenta
Haz varios depósitos y retiradas
Intenta hacer operaciones inválidas para comprobar la protección
Solución propuesta
class CuentaBancaria:
def __init__(self, titular, saldo, iban):
self.titular = titular # setter validará
self.__saldo = saldo
self.__iban = iban
# --- TITULAR ---
@property
def titular(self):
return self.__titular
@titular.setter
def titular(self, nuevo):
if len(nuevo.strip()) < 2:
raise ValueError("El nombre del titular es inválido.")
self.__titular = nuevo
# --- IBAN (solo lectura) ---
@property
def iban(self):
return self.__iban
# --- SALDO ---
def ver_saldo(self):
return self.__saldo
def depositar(self, cantidad):
if cantidad <= 0:
raise ValueError("La cantidad debe ser positiva.")
self.__saldo += cantidad
def retirar(self, cantidad):
if cantidad <= 0:
raise ValueError("La cantidad debe ser positiva.")
if cantidad > self.__saldo:
raise ValueError("Saldo insuficiente.")
self.__saldo -= cantidad
# --- PRUEBAS ---
cuenta = CuentaBancaria("Ana López", 500, "ES12 3456 7890 1234")
cuenta.depositar(200)
cuenta.retirar(100)
print("Titular:", cuenta.titular)
print("IBAN:", cuenta.iban)
print("Saldo:", cuenta.ver_saldo())
# Prueba de validación
try:
cuenta.titular = ""
except ValueError as e:
print("Error:", e)
Ejemplo de salida
Titular: Ana López
IBAN: ES12 3456 7890 1234
Saldo: 600
Error: El nombre del titular es inválido.