Sistema bancario
Parte de la sección Object Oriented Programming del Journey de Python de Coddy — lección 62 de 64.
Desafío
DifícilEn este desafío, construirás un sistema bancario con múltiples tipos de cuentas, transacciones y un gestor bancario central.
Implementa el sistema bancario completando los elementos TODO en estos archivos:
transaction.py- Clase Transaction para registrar actividades financierasaccount.py- Clase base abstracta Account con funcionalidad comúnsavingsaccount.py- Implementación de SavingsAccount con interés y saldo mínimocheckingaccount.py- Implementación de CheckingAccount con capacidades de sobregirobank.py- Clase Bank para gestionar cuentas y transferencias
Hoja de referencia
Este desafío consiste en construir un sistema bancario con conceptos de programación orientada a objetos que incluyen:
- Clase Transaction - Registra actividades financieras
- Clase abstracta Account - Clase base con funcionalidad de cuenta común
- SavingsAccount - Tipo de cuenta con cálculo de intereses y requisitos de saldo mínimo
- CheckingAccount - Tipo de cuenta con capacidades de protección contra sobregiros
- Clase Bank - Gestor central para cuentas y transferencias de dinero
Los conceptos clave incluyen herencia, abstracción, encapsulación y polimorfismo para crear una arquitectura de sistema bancario modular.
Pruébalo tú mismo
from transaction import Transaction
from account import Account
from savingsaccount import SavingsAccount
from checkingaccount import CheckingAccount
from bank import Bank
# Manejador de casos de prueba integral que cubre todos los escenarios y casos límite
test_case = input()
if test_case == "transaction_class":
# Probar la clase Transaction
transaction = Transaction("deposit", 100.50, None)
print(str(transaction))
transaction = Transaction("withdrawal", 75.25, None)
print(str(transaction))
elif test_case == "account_deposit":
# Probar la funcionalidad de depósito
savings = SavingsAccount("S123", "John Doe", 500)
# Cantidad positiva
success, message = savings.deposit(200)
print(f"Success: {success}")
print(f"Message: {message}")
print(f"Balance: ${savings.get_balance():.2f}")
# Cantidad negativa (debería fallar)
success, message = savings.deposit(-50)
print(f"Success: {success}")
print(f"Message: {message}")
elif test_case == "savings_withdraw":
# Probar el retiro de una cuenta de ahorros
savings = SavingsAccount("S123", "John Doe", 500, min_balance=200)
# Retiro válido
success, message = savings.withdraw(100)
print(f"Success: {success}")
print(f"Message: {message}")
# Inválido (por debajo del saldo mínimo)
success, message = savings.withdraw(300)
print(f"Success: {success}")
print(f"Message: {message}")
# Cantidad negativa
success, message = savings.withdraw(-50)
print(f"Success: {success}")
print(f"Message: {message}")
elif test_case == "checking_withdraw":
# Probar el retiro de una cuenta corriente
checking = CheckingAccount("C123", "Jane Smith", 300, overdraft_limit=200)
# Retiro normal
success, message = checking.withdraw(100)
print(f"Success: {success}")
print(f"Message: {message}")
# Retiro con sobregiro
success, message = checking.withdraw(300)
print(f"Success: {success}")
print(f"Message: {message}")
# Excediendo el límite de sobregiro
success, message = checking.withdraw(200)
print(f"Success: {success}")
print(f"Message: {message}")
elif test_case == "interest_application":
# Probar la aplicación de intereses
savings = SavingsAccount("S123", "John Doe", 1000, interest_rate=0.05)
success, message = savings.apply_interest()
print(f"Success: {success}")
print(f"Message: {message}")
print(f"New Balance: ${savings.get_balance():.2f}")
# Verificar el historial de transacciones
transactions = savings.get_transaction_history()
print(f"Transaction count: {len(transactions)}")
print(f"Last transaction: {transactions[-1]}")
elif test_case == "bank_create_account":
# Probar la creación de cuentas bancarias
bank = Bank("Test Bank")
# Crear una cuenta de ahorros
success, message = bank.create_account("savings", "S123", "John Doe", 1000, interest_rate=0.03)
print(f"Success: {success}")
print(f"Message: {message}")
# Crear una cuenta corriente
success, message = bank.create_account("checking", "C456", "Jane Smith", 500, overdraft_limit=300)
print(f"Success: {success}")
print(f"Message: {message}")
# Crear con un número de cuenta duplicado
success, message = bank.create_account("savings", "S123", "Another Person", 200)
print(f"Success: {success}")
print(f"Message: {message}")
# Crear con un tipo inválido
success, message = bank.create_account("invalid", "I789", "Test Person", 100)
print(f"Success: {success}")
print(f"Message: {message}")
elif test_case == "bank_transfer":
# Probar la funcionalidad de transferencia bancaria
bank = Bank("Transfer Test Bank")
# Crear dos cuentas
bank.create_account("savings", "S123", "John Doe", 1000, min_balance=100)
bank.create_account("checking", "C456", "Jane Smith", 500)
# Transferencia válida
success, message = bank.transfer("S123", "C456", 300)
print(f"Success: {success}")
print(f"Message: {message}")
print(f"Source balance: ${bank.get_account('S123').get_balance():.2f}")
print(f"Destination balance: ${bank.get_account('C456').get_balance():.2f}")
# Transferencia inválida (excede el saldo mínimo)
success, message = bank.transfer("S123", "C456", 700)
print(f"Success: {success}")
print(f"Message: {message}")
# Cuenta inválida
success, message = bank.transfer("NONEXISTENT", "C456", 100)
print(f"Success: {success}")
print(f"Message: {message}")
elif test_case == "full_banking_workflow":
# Probar un flujo de trabajo completo
bank = Bank("Full Workflow Bank")
# Crear cuentas
bank.create_account("savings", "S123", "John Doe", 1000, interest_rate=0.05, min_balance=200)
bank.create_account("checking", "C456", "Jane Smith", 500, overdraft_limit=250)
# Realizar depósitos
savings = bank.get_account("S123")
checking = bank.get_account("C456")
savings.deposit(300)
checking.deposit(200)
# Realizar una transferencia
bank.transfer("S123", "C456", 400)
# Aplicar intereses a los ahorros
savings.apply_interest()
# Realizar un retiro de la cuenta corriente con sobregiro
checking.withdraw(900)
# Imprimir el estado final
print("Final Account States:")
print(f"Savings (S123): ${savings.get_balance():.2f}")
print(f"Checking (C456): ${checking.get_balance():.2f}")
print("\nTransaction History (Savings):")
for transaction in savings.get_transaction_history():
print(f"- {transaction}")
print("\nTransaction History (Checking):")
for transaction in checking.get_transaction_history():
print(f"- {transaction}")
elif test_case == "inheritance_validation_test":
# Validación integral de la herencia
objects = []
if 'Transaction' in locals():
objects.append(Transaction('test_param', 100, None))
if 'SavingsAccount' in locals():
objects.append(SavingsAccount('test_param', 'Test User'))
if 'CheckingAccount' in locals():
objects.append(CheckingAccount('test_param', 'Test User'))
if 'Bank' in locals():
objects.append(Bank('test_param'))
for obj in objects:
print(f'{type(obj).__name__}:')
print(f' MRO: {[cls.__name__ for cls in type(obj).__mro__]}')
print()
elif test_case == "method_overriding_test":
# Probar el comportamiento de la anulación de métodos
print('Testing method overriding...')
# Crear instancias y probar métodos anulados
if 'SavingsAccount' in locals():
obj = SavingsAccount('test', 'Test User')
print(f'SavingsAccount methods work correctly')
if 'CheckingAccount' in locals():
obj = CheckingAccount('test', 'Test User')
print(f'CheckingAccount methods work correctly')
elif test_case == "attribute_access_test":
# Probar el acceso a atributos
print('Testing attribute access...')
if 'Transaction' in locals():
obj = Transaction('test', 100, None)
print(f'Transaction attributes accessible')
if 'SavingsAccount' in locals():
obj = SavingsAccount('test', 'Test User')
print(f'SavingsAccount attributes accessible')
if 'CheckingAccount' in locals():
obj = CheckingAccount('test', 'Test User')
print(f'CheckingAccount attributes accessible')
if 'Bank' in locals():
obj = Bank('test')
print(f'Bank attributes accessible')
elif test_case == "boundary_conditions_test":
# Probar condiciones de contorno y valores límite
print('Running boundary_conditions_test test...')
print('Test completed successfully')
elif test_case == "error_handling_test":
# Probar el manejo de errores y escenarios de excepción
print('Running error_handling_test test...')
print('Test completed successfully')
elif test_case == "polymorphic_behavior_test":
# Probar el comportamiento polimórfico con objetos mixtos
print('Running polymorphic_behavior_test test...')
print('Test completed successfully')
elif test_case == "stress_test":
# Prueba de esfuerzo con múltiples objetos
import time
start_time = time.time()
objects = []
for i in range(50):
try:
objects.append(Transaction(f'test_{i}', 100, None))
except:
pass # Manejar errores de creación con elegancia
try:
objects.append(SavingsAccount(f'test_{i}', f'User_{i}'))
except:
pass # Manejar errores de creación con elegancia
try:
objects.append(CheckingAccount(f'test_{i}', f'User_{i}'))
except:
pass # Manejar errores de creación con elegancia
try:
objects.append(Bank(f'test_{i}'))
except:
pass # Manejar errores de creación con elegancia
end_time = time.time()
print(f'Created {len(objects)} objects')
print(f'Time taken: {end_time - start_time:.4f} seconds')
print('Stress test completed')
elif test_case == "comprehensive_validation":
# Prueba de validación integral
print('=== Comprehensive Validation Test ===')
# Prueba 1: Creación básica de objetos
print('1. Basic Object Creation:')
success_count = 0
classes = ['Transaction', 'SavingsAccount', 'CheckingAccount', 'Bank']
try:
obj = Transaction('test', 100, None)
success_count += 1
print(f' Transaction: Created successfully')
except Exception as e:
print(f' Transaction: Creation failed - {e}')
try:
obj = SavingsAccount('test', 'Test User')
success_count += 1
print(f' SavingsAccount: Created successfully')
except Exception as e:
print(f' SavingsAccount: Creation failed - {e}')
try:
obj = CheckingAccount('test', 'Test User')
success_count += 1
print(f' CheckingAccount: Created successfully')
except Exception as e:
print(f' CheckingAccount: Creation failed - {e}')
try:
obj = Bank('test')
success_count += 1
print(f' Bank: Created successfully')
except Exception as e:
print(f' Bank: Creation failed - {e}')
print(f' Successfully created {success_count}/{len(classes)} classes')
print('=== Validation Complete ===')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 Strategy13Desafíos finales
Plataforma de e-learningSistema bancarioDesarrollo de personajes de videojuegosServicio de alquiler de vehículos2Decoradores
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 bancarias