Menu
Coddy logo textTech

Récapitulatif - Gestionnaire de compte bancaire

Fait partie de la section Object Oriented Programming du Journey Python de Coddy — leçon 16 sur 64.

challenge icon

Défi

Moyen

Créez une classe BankAccount complète qui démontre les concepts de programmation orientée objet, y compris les variables de classe, les attributs privés, les propriétés, les getters, les setters et les méthodes. 

1. Créez une classe BankAccount avec :

  • Une variable de classe interest_rate définie sur 0.02 (2%)
  • Des attributs d'instance privés pour __owner_name et __balance
  • Un constructeur qui initialise ces attributs

2. Implémentez les getters et setters de propriété : 

  • Une propriété en lecture seule owner_name qui renvoie le nom du propriétaire du compte
  • Une propriété balance avec :
    • Un getter qui renvoie le solde actuel
    • Un setter qui valide les dépôts (rejetant les montants négatifs)
    • Si la validation échoue, affichez : "Balance cannot be negative"

3. Implémentez les méthodes :

  • deposit(amount) qui :
    • Ajoute au solde si le montant est positif
    • Affiche "Deposit amount must be positive" et renvoie False si le montant n'est pas positif
    • Renvoie True en cas de succès
  • withdraw(amount) qui :
    • Soustrait du solde si le montant est positif et que les fonds sont suffisants
    • Affiche "Withdrawal amount must be positive" et renvoie False si le montant n'est pas positif
    • Affiche "Insufficient funds" et renvoie False si le montant dépasse le solde
    • Renvoie True en cas de succès
  • apply_interest() qui :
    • Ajoute des intérêts au solde en fonction du taux d'intérêt de la classe
    • Renvoie le montant des intérêts
  • display_info() qui affiche les détails du compte dans ce format :

    Account Owner: [owner_name]
    Balance: $[balance]
    Interest Rate: [interest_rate]%

Exigences relatives au format de sortie

  • Tous les messages d'erreur de validation doivent être affichés exactement comme spécifié
  • La méthode display_info() doit formater la sortie exactement comme indiqué ci-dessus
  • Le taux d'intérêt doit être affiché sous forme de pourcentage (multiplier par 100)

Aide-mémoire

Une classe complète illustrant les concepts de la programmation orientée objet :

class BankAccount:
    interest_rate = 0.02  # Variable de classe
    
    def __init__(self, owner_name, initial_balance):
        self.__owner_name = owner_name  # Attribut privé
        self.__balance = initial_balance  # Attribut privé
    
    @property
    def owner_name(self):  # Propriété en lecture seule
        return self.__owner_name
    
    @property
    def balance(self):  # Accesseur (Getter)
        return self.__balance
    
    @balance.setter
    def balance(self, value):  # Mutateur (Setter) avec validation
        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}%")

Concepts clés :

  • Variables de classe : Partagées par toutes les instances
  • Attributs privés : Utilisation du préfixe double souligné (__)
  • Propriétés : Utilisation du décorateur @property pour les accesseurs (getters)
  • Mutateurs (Setters) : Utilisation du décorateur @property_name.setter
  • Validation : Vérifier les conditions et fournir des messages d'erreur

Essayez vous-même

from bank_account import BankAccount

# Gestionnaire de cas de test
test_case = input()

if test_case == "account_creation":
    # Tester la création de compte
    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":
    # Tester la fonctionnalité de dépôt
    account = BankAccount("Bob", 500)
    print(f"Initial balance: ${account.balance}")
    
    # Dépôt valide
    result = account.deposit(300)
    print(f"Deposit result: {result}")
    print(f"New balance: ${account.balance}")
    
    # Dépôt invalide
    result = account.deposit(-50)
    print(f"Negative deposit result: {result}")
    print(f"Balance after invalid deposit: ${account.balance}")

elif test_case == "withdraw_method":
    # Tester la fonctionnalité de retrait
    account = BankAccount("Charlie", 1000)
    
    # Retrait valide
    result = account.withdraw(400)
    print(f"Withdrawal result: {result}")
    print(f"Balance after withdrawal: ${account.balance}")
    
    # Retrait invalide (négatif)
    result = account.withdraw(-50)
    print(f"Negative withdrawal result: {result}")
    
    # Retrait invalide (dépasse le solde)
    result = account.withdraw(1000)
    print(f"Excessive withdrawal result: {result}")
    print(f"Final balance: ${account.balance}")

elif test_case == "property_access":
    # Tester l'accès aux propriétés et la protection
    account = BankAccount("Dave", 800)
    
    print(f"Owner via property: {account.owner_name}")
    print(f"Balance via property: ${account.balance}")
    
    # Essayer de définir le solde (devrait utiliser le setter)
    account.balance = 1200
    print(f"Balance after valid setter: ${account.balance}")
    
    # Essayer un solde invalide
    account.balance = -500
    print(f"Balance after invalid setter: ${account.balance}")
    
    # Essayer d'accéder directement aux attributs privés (devrait échouer)
    try:
        print(account.__owner_name)
    except AttributeError:
        print("Cannot access private owner_name directly")

elif test_case == "apply_interest":
    # Tester l'application des intérêts
    account = BankAccount("Eve", 2000)
    
    # Vérifier le solde initial
    print(f"Initial balance: ${account.balance}")
    
    # Appliquer les intérêts
    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":
    # Tester le format de la méthode display_info
    account = BankAccount("Frank", 1500)
    
    # Modifier le taux d'intérêt pour tester la variable de classe
    original_rate = BankAccount.interest_rate
    BankAccount.interest_rate = 0.03
    
    print("Display info output:")
    account.display_info()
    
    # Restaurer le taux original
    BankAccount.interest_rate = original_rate

elif test_case == "original_test_case":
    # Exécuter le code de test original du défi
    account = BankAccount("Coddy", 1000)

    # Effectuer des opérations
    account.deposit(500)
    account.withdraw(200)
    account.apply_interest()

    # Afficher les informations du compte
    account.display_info()

    # Tester la validation du setter
    account.balance = 5000
    print(f"Balance after setter: ${account.balance}")

    # Tester la validation du retrait
    account.withdraw(10000)
    print(f"Final balance: ${account.balance}")

Toutes les leçons de Object Oriented Programming