Menu
Coddy logo textTech

Resumen - Gestor de cuentas bancarias

Parte de la sección Object Oriented Programming del Journey de Python de Coddy — lección 16 de 64.

challenge icon

Desafío

Intermedio

Crea 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_rate establecida en 0.02 (2%)
  • Atributos de instancia privados para __owner_name y __balance
  • Un constructor que inicialice estos atributos

2. Implementa getters y setters de propiedades: 

  • Una propiedad de solo lectura owner_name que devuelva el nombre del propietario de la cuenta
  • Una propiedad balance con:
    • 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 devuelva False si la cantidad no es positiva
    • Devuelva True en 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 devuelva False si la cantidad no es positiva
    • Imprima "Insufficient funds" y devuelva False si la cantidad excede el saldo
    • Devuelva True en 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 @property para 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