Ocultamiento de información
Parte de la sección Object Oriented Programming del Journey de Python de Coddy — lección 30 de 64.
El ocultamiento de información restringe el acceso directo a los componentes del objeto, requiriendo que todas las interacciones ocurran a través de interfaces bien definidas. Esto protege los datos internos del acceso no autorizado.
Aquí hay un ejemplo de una clase con diferentes 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 - uso interno
self.__account_number = "ACC123456" # Privado - oculto desde el exteriorAgrega 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 a los datos públicos directamente:
print(account.owner) # Alice - acceso público OKUsa métodos controlados para datos protegidos:
print(account.get_balance()) # 1000 - acceso controlado
account.deposit(500)
print(account.get_balance()) # 1500 - el saldo cambió 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 está sujeto a "name mangling" pero sigue siendo técnicamente accesible:
# Esto funciona pero viola la 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 luego proporcionar acceso controlado a través de métodos públicos. Esto evita la manipulación directa de datos sensibles y garantiza la integridad de los datos 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 TODO detallados para guiar tu implementación.
Los requisitos clave incluyen:
- Encapsulación adecuada de credenciales y mensajes
- Autenticación antes de permitir operaciones de mensajes
- Monitoreo de seguridad a través del seguimiento de intentos de inicio de sesión
- Mensajes de retorno precisos según lo especificado en los TODOs
Hoja de referencia
El ocultamiento de información restringe el acceso directo a los componentes de un objeto a través de modificadores de acceso:
public- accesible directamente (sin guion bajo)_protected- uso interno (un solo guion bajo)__private- oculto desde el exterior (doble guion bajo)
class BankAccount:
def __init__(self, owner, initial_balance):
self.owner = owner # Público
self._balance = initial_balance # Protegido
self.__account_number = "ACC123456" # PrivadoProporcione acceso controlado a través de métodos públicos:
def get_balance(self):
return self._balance
def deposit(self, amount):
if amount > 0:
self._balance += amount
return True
return FalseLos atributos privados están sujetos a la deformación de nombres (name-mangling) pero siguen siendo accesibles:
# Viola el ocultamiento de información pero funciona:
print(account._BankAccount__account_number)Pruébalo tú mismo
from securemessenger import SecureMessenger
# Manejador de casos de prueba
test_case = input()
if test_case == "default_test":
# Caso de prueba estándar del problema original
messenger = SecureMessenger("user1")
# Intentar añadir mensajes antes de iniciar sesión
print(messenger.add_message("Hello World!"))
print(messenger.add_message("Secure Message"))
# Intento de inicio de sesión con contraseña incorrecta
print(messenger.login("wrong_pass"))
# Inicio de sesión con contraseña correcta
print(messenger.login("secure123"))
# Añadir mensajes después de un inicio de sesión exitoso
print(messenger.add_message("Hello World!"))
print(messenger.add_message("Secure Message"))
# Recuperar mensajes
print(messenger.get_messages())
# Verificar intentos de inicio de sesión
print(messenger.get_login_attempts())
elif test_case == "custom_password":
# Prueba con 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":
# Probar múltiples 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":
# Probar la gestión de mensajes
messenger = SecureMessenger("user3")
print(messenger.login("secure123"))
# Añadir múltiples mensajes
messages = ["Message 1", "Message 2", "Message 3", "Message 4", "Message 5"]
for msg in messages:
print(messenger.add_message(msg))
# Verificar todos los mensajes
print(messenger.get_messages())
elif test_case == "empty_messages":
# Probar caso de mensajes vacíos
messenger = SecureMessenger("user4")
print(messenger.login("secure123"))
print(messenger.get_messages())
elif test_case == "access_without_login":
# Probar acceso sin iniciar sesión
messenger = SecureMessenger("user5")
print(messenger.add_message("Unauthorized message"))
print(messenger.get_messages())
elif test_case == "attribute_privacy":
# Probar la privacidad de los atributos
messenger = SecureMessenger("user6")
# Atributo público
print(f"Public username: {messenger.username}")
# Atributos privados - estos deberían lanzar 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 extender la clase con un método de cierre de sesión
# Para fines de 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 esfuerzo con muchos mensajes
messenger = SecureMessenger("user8")
print(messenger.login("secure123"))
# Añadir 100 mensajes
for i in range(1, 101):
messenger.add_message(f"Message {i}")
# Verificar el recuento de mensajes
messages = messenger.get_messages()
newline_char = '\n' # Almacenar 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 Object Oriented Programming
1Fundamentos de la POO
Archivos externosIntroducción a la POOClases vs ObjetosEl parámetro selfMétodosAtributosMétodo constructor (__init__)Resumen - Calculadora simple4Herencia
Herencia básicaLa función super()Sobrescritura de métodosHerencia múltipleOrden de resolución de métodosResumen - 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 propertyDecorador de métodos estáticosDecorador de métodos de clase5Polimorfismo
Sobreescritura de métodos revisitadaDuck TypingClases y métodos abstractosDiseño de interfacesResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. 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 de claseDecoradores de propiedadesAtributos privadosResumen - Gestor de cuentas bancarias6Encapsulamiento
Miembros públicos, protegidos y privadosModificadores de accesoOcultamiento de informaciónDecoradores de propiedades avanzadosResumen - Sistema de registros de estudiantes