Menu
Coddy logo textTech

まとめ - 銀行口座マネージャー

CoddyのPythonジャーニー「Object Oriented Programming」セクションの一部 — レッスン 16/64。

challenge icon

チャレンジ

中級

クラス変数、プライベート属性、プロパティ、ゲッター、セッター、およびメソッドを含むオブジェクト指向プログラミングの概念を実証する、完全な BankAccount クラスを作成してください。 

1. 以下の内容で BankAccount クラスを作成します:

  • クラス変数 interest_rate0.02 (2%) に設定します
  • __owner_name__balance のプライベートインスタンス属性
  • これらの属性を初期化するコンストラクタ

2. プロパティのゲッターとセッターを実装します: 

  • アカウント所有者の名前を返す読み取り専用プロパティ owner_name
  • 以下の機能を持つプロパティ balance
    • 現在の残高を返すゲッター
    • 入金を検証するセッター(負の金額を拒否する)
    • 検証に失敗した場合は、"Balance cannot be negative" と出力します

3. メソッドを実装します:

  • deposit(amount)
    • 金額が正の場合、残高に加算します
    • 金額が正でない場合は "Deposit amount must be positive" と出力し、False を返します
    • 成功した場合は True を返します
  • withdraw(amount)
    • 金額が正で、かつ資金が十分な場合、残高から差し引きます
    • 金額が正でない場合は "Withdrawal amount must be positive" と出力し、False を返します
    • 金額が残高を超える場合は "Insufficient funds" と出力し、False を返します
    • 成功した場合は True を返します
  • apply_interest()
    • クラスの利率に基づいて残高に利息を加算します
    • 利息額を返します
  • display_info():以下の形式でアカウントの詳細を出力します:

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

出力形式の要件

  • すべての検証エラーメッセージは、指定された通りに正確に出力する必要があります
  • display_info() メソッドは、上記に示された通りに正確に出力をフォーマットする必要があります
  • 利率はパーセンテージとして表示する必要があります(100を掛けます)

チートシート

オブジェクト指向プログラミングの概念を実演する完全なクラスの例です:

class BankAccount:
    interest_rate = 0.02  # クラス変数
    
    def __init__(self, owner_name, initial_balance):
        self.__owner_name = owner_name  # プライベート属性
        self.__balance = initial_balance  # プライベート属性
    
    @property
    def owner_name(self):  # 読み取り専用プロパティ
        return self.__owner_name
    
    @property
    def balance(self):  # ゲッター
        return self.__balance
    
    @balance.setter
    def balance(self, value):  # バリデーション付きセッター
        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}%")

主要な概念:

  • クラス変数: すべてのインスタンスで共有されます
  • プライベート属性: 二重アンダースコアの接頭辞(__)を使用します
  • プロパティ: ゲッターには @property デコレータを使用します
  • セッター: @property_name.setter デコレータを使用します
  • バリデーション: 条件をチェックし、エラーメッセージを提供します

自分で試してみよう

from bank_account import BankAccount

# テストケースのハンドラー
test_case = input()

if test_case == "account_creation":
    # アカウント作成のテスト
    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":
    # 入金機能のテスト
    account = BankAccount("Bob", 500)
    print(f"Initial balance: ${account.balance}")
    
    # 有効な入金
    result = account.deposit(300)
    print(f"Deposit result: {result}")
    print(f"New balance: ${account.balance}")
    
    # 無効な入金
    result = account.deposit(-50)
    print(f"Negative deposit result: {result}")
    print(f"Balance after invalid deposit: ${account.balance}")

elif test_case == "withdraw_method":
    # 出金機能のテスト
    account = BankAccount("Charlie", 1000)
    
    # 有効な出金
    result = account.withdraw(400)
    print(f"Withdrawal result: {result}")
    print(f"Balance after withdrawal: ${account.balance}")
    
    # 無効な出金(負の数)
    result = account.withdraw(-50)
    print(f"Negative withdrawal result: {result}")
    
    # 無効な出金(残高不足)
    result = account.withdraw(1000)
    print(f"Excessive withdrawal result: {result}")
    print(f"Final balance: ${account.balance}")

elif test_case == "property_access":
    # プロパティのアクセスと保護のテスト
    account = BankAccount("Dave", 800)
    
    print(f"Owner via property: {account.owner_name}")
    print(f"Balance via property: ${account.balance}")
    
    # 残高の設定を試行(セッターを使用すべき)
    account.balance = 1200
    print(f"Balance after valid setter: ${account.balance}")
    
    # 無効な残高を試行
    account.balance = -500
    print(f"Balance after invalid setter: ${account.balance}")
    
    # プライベート属性への直接アクセスを試行(失敗するはず)
    try:
        print(account.__owner_name)
    except AttributeError:
        print("Cannot access private owner_name directly")

elif test_case == "apply_interest":
    # 利息適用のテスト
    account = BankAccount("Eve", 2000)
    
    # 元の残高を確認
    print(f"Initial balance: ${account.balance}")
    
    # 利息を適用
    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":
    # display_info メソッドの形式をテスト
    account = BankAccount("Frank", 1500)
    
    # クラス変数をテストするために利率を変更
    original_rate = BankAccount.interest_rate
    BankAccount.interest_rate = 0.03
    
    print("Display info output:")
    account.display_info()
    
    # 元の利率を復元
    BankAccount.interest_rate = original_rate

elif test_case == "original_test_case":
    # チャレンジの元のテストコードを実行
    account = BankAccount("Coddy", 1000)

    # 操作を実行
    account.deposit(500)
    account.withdraw(200)
    account.apply_interest()

    # アカウント情報を表示
    account.display_info()

    # セッターのバリデーションをテスト
    account.balance = 5000
    print(f"Balance after setter: ${account.balance}")

    # 出金のバリデーションをテスト
    account.withdraw(10000)
    print(f"Final balance: ${account.balance}")

Object Oriented Programmingのすべてのレッスン