Resumen - Gestor de cuentas bancarias
Parte de la sección Object Oriented Programming del Journey de Python de Coddy — lección 16 de 64.
Desafío
IntermedioCrea una clase BankAccount completa que demuestre conceptos de programación orientada a objetos, incluyendo variables de clase, atributos privados, propiedades, getters, setters y métodos.
1. Crea una clase BankAccount con:
- Una variable de clase
interest_rateestablecida en0.02(2%) - Atributos de instancia privados para
__owner_namey__balance - Un constructor que inicialice estos atributos
2. Implementa getters y setters de propiedades:
- Una propiedad de solo lectura
owner_nameque devuelva el nombre del propietario de la cuenta - Una propiedad
balancecon:- Un getter que devuelva el saldo actual
- Un setter que valide los depósitos (rechazando cantidades negativas)
- Si la validación falla, imprime:
"Balance cannot be negative"
3. Implementa métodos:
deposit(amount)que:- Añada al saldo si la cantidad es positiva
- Imprima
"Deposit amount must be positive"y devuelvaFalsesi la cantidad no es positiva - Devuelva
Trueen caso de éxito
withdraw(amount)que:- Reste del saldo si la cantidad es positiva y los fondos son suficientes
- Imprima
"Withdrawal amount must be positive"y devuelvaFalsesi la cantidad no es positiva - Imprima
"Insufficient funds"y devuelvaFalsesi la cantidad excede el saldo - Devuelva
Trueen caso de éxito
apply_interest()que:- Añada intereses al saldo basándose en la tasa de interés de la clase
- Devuelva la cantidad de interés
display_info()que imprima los detalles de la cuenta en este formato:Account Owner: [owner_name] Balance: $[balance] Interest Rate: [interest_rate]%
Requisitos del Formato de Salida
- Todos los mensajes de error de validación deben imprimirse exactamente como se especifica
- El método
display_info()debe formatear la salida exactamente como se muestra arriba - La tasa de interés debe mostrarse como un porcentaje (multiplicar por 100)
Hoja de referencia
Una clase completa que demuestra conceptos de programación orientada a objetos:
class BankAccount:
interest_rate = 0.02 # Variable de clase
def __init__(self, owner_name, initial_balance):
self.__owner_name = owner_name # Atributo privado
self.__balance = initial_balance # Atributo privado
@property
def owner_name(self): # Propiedad de solo lectura
return self.__owner_name
@property
def balance(self): # Getter
return self.__balance
@balance.setter
def balance(self, value): # Setter con validación
if value < 0:
print("Balance cannot be negative")
else:
self.__balance = value
def deposit(self, amount):
if amount <= 0:
print("Deposit amount must be positive")
return False
self.__balance += amount
return True
def withdraw(self, amount):
if amount <= 0:
print("Withdrawal amount must be positive")
return False
if amount > self.__balance:
print("Insufficient funds")
return False
self.__balance -= amount
return True
def apply_interest(self):
interest = self.__balance * self.interest_rate
self.__balance += interest
return interest
def display_info(self):
print(f"Account Owner: {self.__owner_name}")
print(f"Balance: ${self.__balance}")
print(f"Interest Rate: {self.interest_rate * 100}%")
Conceptos clave:
- Variables de clase: Compartidas entre todas las instancias
- Atributos privados: Utilizan el prefijo de doble guion bajo (
__) - Propiedades: Utilizan el decorador
@propertypara los getters - Setters: Utilizan el decorador
@property_name.setter - Validación: Verificar condiciones y proporcionar mensajes de error
Pruébalo tú mismo
from bank_account import BankAccount
# Manejador de casos de prueba
test_case = input()
if test_case == "account_creation":
# Probar la creación de cuenta
account = BankAccount("Alice", 1000)
print(f"Owner: {account.owner_name}")
print(f"Initial balance: ${account.balance}")
print(f"Interest rate: {BankAccount.interest_rate * 100}%")
elif test_case == "deposit_method":
# Probar la funcionalidad de depósito
account = BankAccount("Bob", 500)
print(f"Initial balance: ${account.balance}")
# Depósito válido
result = account.deposit(300)
print(f"Deposit result: {result}")
print(f"New balance: ${account.balance}")
# Depósito inválido
result = account.deposit(-50)
print(f"Negative deposit result: {result}")
print(f"Balance after invalid deposit: ${account.balance}")
elif test_case == "withdraw_method":
# Probar la funcionalidad de retiro
account = BankAccount("Charlie", 1000)
# Retiro válido
result = account.withdraw(400)
print(f"Withdrawal result: {result}")
print(f"Balance after withdrawal: ${account.balance}")
# Retiro inválido (negativo)
result = account.withdraw(-50)
print(f"Negative withdrawal result: {result}")
# Retiro inválido (excede el saldo)
result = account.withdraw(1000)
print(f"Excessive withdrawal result: {result}")
print(f"Final balance: ${account.balance}")
elif test_case == "property_access":
# Probar el acceso a propiedades y protección
account = BankAccount("Dave", 800)
print(f"Owner via property: {account.owner_name}")
print(f"Balance via property: ${account.balance}")
# Intentar establecer el saldo (debería usar el setter)
account.balance = 1200
print(f"Balance after valid setter: ${account.balance}")
# Intentar saldo inválido
account.balance = -500
print(f"Balance after invalid setter: ${account.balance}")
# Intentar acceder a atributos privados directamente (debería fallar)
try:
print(account.__owner_name)
except AttributeError:
print("Cannot access private owner_name directly")
elif test_case == "apply_interest":
# Probar la aplicación de intereses
account = BankAccount("Eve", 2000)
# Verificar el saldo original
print(f"Initial balance: ${account.balance}")
# Aplicar intereses
interest_earned = account.apply_interest()
expected_interest = 2000 * 0.02
print(f"Interest earned: ${interest_earned}")
print(f"New balance after interest: ${account.balance}")
print(f"Interest calculation correct: {interest_earned == expected_interest}")
elif test_case == "display_info":
# Probar el formato del método display_info
account = BankAccount("Frank", 1500)
# Modificar la tasa de interés para probar la variable de clase
original_rate = BankAccount.interest_rate
BankAccount.interest_rate = 0.03
print("Display info output:")
account.display_info()
# Restaurar la tasa original
BankAccount.interest_rate = original_rate
elif test_case == "original_test_case":
# Ejecutar el código de prueba original del desafío
account = BankAccount("Coddy", 1000)
# Realizar operaciones
account.deposit(500)
account.withdraw(200)
account.apply_interest()
# Mostrar información de la cuenta
account.display_info()
# Probar la validación del setter
account.balance = 5000
print(f"Balance after setter: ${account.balance}")
# Probar la validación de retiro
account.withdraw(10000)
print(f"Final balance: ${account.balance}")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 bancarias