Ocultación de información
Parte de la sección Programación orientada a objetos del Journey de Python de Coddy. Lección 30 de 64.
La ocultación de información restringe el acceso directo a los componentes de un objeto y exige que todas las interacciones se realicen a través de interfaces bien definidas. Esto protege los datos internos del acceso no autorizado.
Aquí tienes un ejemplo de una clase con distintos niveles de ocultación de información:
class BankAccount:
def __init__(self, owner, initial_balance):
self.owner = owner # Público - se puede acceder directamente
self._balance = initial_balance # Protegido - para uso interno
self.__account_number = "ACC123456" # Privado - oculto desde el exteriorAñade métodos que proporcionen acceso controlado a los datos ocultos:
class BankAccount:
def __init__(self, owner, initial_balance):
self.owner = owner
self._balance = initial_balance
self.__account_number = "ACC123456"
def deposit(self, amount):
if amount > 0:
self._balance += amount
return True
return False
def withdraw(self, amount):
if amount > 0 and amount <= self._balance:
self._balance -= amount
return True
return False
def get_balance(self):
return self._balance
def get_account_info(self):
# Forma segura de mostrar datos privados parciales
return f"Owner: {self.owner}, Account: ***{self.__account_number[-4:]}"Usa la clase a través de su interfaz pública:
account = BankAccount("Alice", 1000)Accede directamente a los datos públicos:
print(account.owner) # Alice - acceso público permitidoUsa métodos controlados para los datos protegidos:
print(account.get_balance()) # 1000 - acceso controlado
account.deposit(500)
print(account.get_balance()) # 1500 - saldo modificado de forma seguraIntenta acceder a los datos ocultos:
print(account.get_account_info()) # Propietario: Alice, Cuenta: ***3456
# print(account.__account_number) # AttributeError - ocultoEl atributo privado tiene su nombre manipulado, pero sigue siendo técnicamente accesible:
# Esto funciona, pero vulnera el principio de ocultación de información:
print(account._BankAccount__account_number) # ACC123456Salida:
Alice
1000
1500
Owner: Alice, Account: ***3456
ACC123456Punto clave: La ocultación de información protege los datos internos al hacerlos privados o protegidos y después proporcionar acceso controlado mediante métodos públicos. Esto evita la manipulación directa de datos confidenciales y garantiza su integridad mediante la validación en los métodos de acceso.
Desafío
IntermedioEn este desafío, implementarás un sistema de mensajería seguro con pruebas exhaustivas para validar tu solución.
Debes editar securemessenger.py para implementar la clase SecureMessenger siguiendo los principios de ocultación de información. El archivo contiene comentarios detallados de TODO para guiar tu implementación.
Los requisitos principales incluyen:
- Encapsulación adecuada de las credenciales y los mensajes
- Autenticación antes de permitir operaciones con mensajes
- Supervisión de seguridad mediante el seguimiento de los intentos de inicio de sesión
- Mensajes de retorno precisos, según se especifica en los TODO
Pruébalo tú mismo
from securemessenger import SecureMessenger
# Gestor de casos de prueba
test_case = input()
if test_case == "default_test":
# Caso de prueba estándar del problema original
messenger = SecureMessenger("user1")
# Intenta añadir mensajes antes de iniciar sesión
print(messenger.add_message("Hello World!"))
print(messenger.add_message("Secure Message"))
# Intenta iniciar sesión con una contraseña incorrecta
print(messenger.login("wrong_pass"))
# Inicia sesión con la contraseña correcta
print(messenger.login("secure123"))
# Añade mensajes después de iniciar sesión correctamente
print(messenger.add_message("Hello World!"))
print(messenger.add_message("Secure Message"))
# Recupera los mensajes
print(messenger.get_messages())
# Comprueba los intentos de inicio de sesión
print(messenger.get_login_attempts())
elif test_case == "custom_password":
# Prueba con una contraseña personalizada
messenger = SecureMessenger("admin", "admin123")
print(messenger.login("wrong_password"))
print(messenger.login("admin123"))
print(messenger.get_login_attempts())
elif test_case == "multiple_login_attempts":
# Prueba varios intentos de inicio de sesión
messenger = SecureMessenger("user2")
print(messenger.login("attempt1"))
print(messenger.login("attempt2"))
print(messenger.login("attempt3"))
print(messenger.login("secure123"))
print(messenger.get_login_attempts())
elif test_case == "message_management":
# Gestión de Test message
messenger = SecureMessenger("user3")
print(messenger.login("secure123"))
# Añade varios mensajes
messages = ["Message 1", "Message 2", "Message 3", "Message 4", "Message 5"]
for msg in messages:
print(messenger.add_message(msg))
# Verifica todos los mensajes
print(messenger.get_messages())
elif test_case == "empty_messages":
# Prueba el caso de mensajes vacíos
messenger = SecureMessenger("user4")
print(messenger.login("secure123"))
print(messenger.get_messages())
elif test_case == "access_without_login":
# Prueba el acceso sin iniciar sesión
messenger = SecureMessenger("user5")
print(messenger.add_message("Unauthorized message"))
print(messenger.get_messages())
elif test_case == "attribute_privacy":
# Prueba la privacidad de los atributos
messenger = SecureMessenger("user6")
# Atributo público
print(f"Public username: {messenger.username}")
# Atributos privados: estos deberían generar AttributeError
try:
print(messenger.__password)
except AttributeError as e:
print("Password is private: AttributeError")
try:
print(messenger.__messages)
except AttributeError as e:
print("Messages are private: AttributeError")
try:
print(messenger.__login_attempts)
except AttributeError as e:
print("Login attempts are private: AttributeError")
try:
print(messenger.__is_logged_in)
except AttributeError as e:
print("Login status is private: AttributeError")
elif test_case == "login_logout_sequence":
# Esta prueba requiere ampliar la clase con un método logout
# Para realizar la prueba, crearemos una subclase con funcionalidad de cierre de sesión
class ExtendedMessenger(SecureMessenger):
def logout(self):
self._SecureMessenger__is_logged_in = False
return "Logged out successfully"
messenger = ExtendedMessenger("user7")
print(messenger.login("secure123"))
print(messenger.add_message("Test message"))
print(messenger.get_messages())
print(messenger.logout())
print(messenger.get_messages())
elif test_case == "stress_test":
# Prueba de estrés con muchos mensajes
messenger = SecureMessenger("user8")
print(messenger.login("secure123"))
# Añade 100 mensajes
for i in range(1, 101):
messenger.add_message(f"Message {i}")
# Verifica la cantidad de mensajes
messages = messenger.get_messages()
newline_char = '\n' # Guarda el carácter de nueva línea en una variable
message_count = len(messages.split(newline_char))
print(f"Added 100 messages. Retrieved {message_count} messages.")Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Fundamentos de la POO
Introducción a la POOArchivos externosClases vs. objetosEl parámetro selfMétodosAtributosMétodo constructor (__init__)Repaso: calculadora sencilla4Herencia
Herencia básicaLa función super()Sobrescritura de métodosHerencia múltipleOrden de resolución de métodosRepaso: jerarquía de empleados7Métodos especiales
Introducción a los métodos mágicosSobrecarga de operadoresMétodos mágicos de contenedoresRepaso: lista personalizada10Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy2Decoradores
Introducción a los decoradoresDecorador de propiedadDecorador de método estáticoDecorador de método de clase5Polimorfismo
Repaso de la sobrescritura de métodosTipado patoClases y métodos abstractosDiseño de interfacesRepaso: calculadora de formas8Conceptos avanzados de POO
Composición frente a herenciaMixinsMétodos estáticos y de claseDecoradores de claseGestores de contexto11Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite3Propiedades de clase
Variables de instancia vs. variables de claseDecoradores de propiedadesAtributos privadosRepaso: gestor de cuentas bancarias6Encapsulamiento
Miembros públicos, protegidos y privadosModificadores de accesoOcultación de informaciónDecoradores de propiedades avanzadosRepaso: sistema de registros de estudiantesPractica por tu cuenta: Compilador de Python online