Menu
Coddy logo textTech

Итоги — Менеджер банковского счета

Часть раздела Object Oriented Programming путешествия по Python на Coddy — урок 16 из 64.

challenge icon

Задание

Средне

Создайте полный класс BankAccount, который демонстрирует концепции объектно-ориентированного программирования, включая переменные класса, приватные атрибуты, свойства, геттеры, сеттеры и методы. 

1. Создайте класс BankAccount с:

  • Переменной класса interest_rate, установленной в 0.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