Encapsulación en Python: atributos privados y métodos getter/setter

Clase 4 de 17Curso de Python Orientado a Objetos

Resumen

La encapsulación en Python te ayuda a proteger datos sensibles y a mantener la integridad de tu aplicación. Con un ejemplo claro de una biblioteca, se muestra cómo controlar el acceso a los atributos internos con atributos privados, validaciones y métodos getter y setter para evitar inconsistencias.

¿Qué es la encapsulación en Python y cómo protege tus datos?

La idea es simple: como en un banco, no accedes a la bóveda, hablas con el cajero. En Python, la encapsulación oculta los detalles internos de una clase y controla el acceso a los datos. En un sistema de biblioteca, esto asegura la integridad de datos: nadie debería alterar desde fuera el estado real de un libro.

¿Cómo evitar inconsistencias con préstamos y disponibilidad?

  • Controla el flujo con un atributo de disponibilidad: si está disponible, se presta; si no, se informa que “no está disponible”.
  • Evita retornos implícitos de None: devuelve un mensaje claro cuando no se puede prestar.
  • Incrementa un contador interno de veces prestado al ejecutar el método prestar.
  • Usa espopular para evaluar si un libro es popular: retorna true si fue prestado más de cinco veces.

¿Qué problema surge al modificar datos directamente?

  • Si desde fuera haces libro.veces_prestado = 10, el sistema mostrará “total préstamos 11” sin que haya ocurrido realmente. Esto rompe la integridad del dato.
  • La solución: encapsular el contador y exponer acceso controlado con métodos.

¿Cuándo usar un guion bajo y cuándo dos?

Python ofrece dos niveles de señalización para atributos internos.

¿Qué significa un solo guion bajo?

  • Un solo guion bajo (por ejemplo, _veces_prestado) es una convención: indica “no toques esto desde fuera”.
  • Aun así, es accesible externamente. Sirve como recordatorio, no como barrera real.

¿Qué hace el doble guion bajo?

  • Con doble guion bajo (__veces_prestado) se activa el name mangling: no podrás acceder directamente desde fuera del objeto.
  • Si intentas leer o modificar ese atributo desde fuera, obtendrás un error: el mensaje indica que el atributo es interno y debe manejarse dentro de la clase.

¿Cómo implementar getters y setters con validaciones?

Para exponer datos de forma segura, crea un getter para leer y un setter para modificar con validaciones. Además, ajusta métodos como prestar y espopular para mantener coherencia.

class Libro: def __init__(self, titulo, veces_prestado=0, disponible=True): # *init* self.titulo = titulo self.__veces_prestado = veces_prestado self.disponible = disponible def prestar(self): if self.disponible: self.__veces_prestado += 1 self.disponible = False return f"Prestado exitosamente. Total préstamos: {self.__veces_prestado}." else: return "No está disponible." # evita None def espopular(self): return self.__veces_prestado > 5 def get_veces_prestado(self): # *getter* return self.__veces_prestado def set_veces_prestado(self, veces): # *setter* # Aquí podrías validar orígenes confiables o rangos permitidos. self.__veces_prestado = veces

¿Qué habilidades y conceptos prácticos se aplican?

  • Diseño con programación orientada a objetos: clases, métodos y atributos.
  • Control de acceso con atributos privados y convención de guiones bajos.
  • Implementación de getter y setter para validar lectura y escritura.
  • Manejo de estados: disponible/no disponible para evitar retornos inesperados como None.
  • Lógica de negocio con espopular para medir uso real (> 5 préstamos).
  • Criterios de encapsulación: “¿Debe un usuario externo modificar esta variable interna?” Si no, hazla privada y expón métodos con validaciones.

¿Te gustaría compartir cómo encapsularías otros atributos críticos de tu proyecto y qué validaciones agregarías en tus setters?