Объектно-ориентированное программирование в Python
ООП организует программу вокруг объектов, которые хранят состояние и предоставляют поведение через понятные интерфейсы.
Что такое объектно-ориентированное программирование в Python?
ООП моделирует систему как взаимодействующие объекты. Каждый объект объединяет состояние и допустимые операции, что проясняет ответственность в больших программах.
Четыре основных принципа ООП
- Инкапсуляция объединяет состояние и поведение и контролирует доступ.
- Абстракция показывает полезный интерфейс и скрывает лишние детали.
- Наследование специализирует класс только при настоящем отношении «является».
- Полиморфизм применяет одну операцию к разным объектам с подходящим поведением.
Устройство примера
- BankAccount хранит баланс и проверяет пополнение.
- SavingsAccount повторно использует базовый контракт.
- SavingsAccount переопределяет month_end для начисления процентов.
- Цикл использует единый интерфейс для всех счетов.
Базовый пример
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self._balance = float(balance)
@property
def balance(self):
return self._balance
def deposit(self, amount):
if amount <= 0:
raise ValueError("Deposit must be positive")
self._balance += amount
def month_end(self):
return "No interest"
class SavingsAccount(BankAccount):
def __init__(self, owner, balance, interest_rate):
super().__init__(owner, balance)
self.interest_rate = interest_rate
def month_end(self):
self._balance *= 1 + self.interest_rate
return "Interest applied"
accounts = [
BankAccount("Ada", 100),
SavingsAccount("Lin", 200, 0.05),
]
accounts[0].deposit(50)
for account in accounts:
status = account.month_end()
print(f"{account.owner}: {account.balance:.2f} ({status})")
Ожидаемый результат
Ada: 150.00 (No interest)
Lin: 210.00 (Interest applied)
Четыре принципа ООП на практике
Эти примеры показывают, как Python реализует инкапсуляцию, абстракцию, наследование и полиморфизм в повседневном коде.
Инкапсуляция
Инкапсуляция объединяет состояние и поведение и контролирует доступ.
class BankAccount:
def __init__(self, balance=0):
# Double underscores prevent accidental direct access.
self.__balance = balance
@property
def balance(self):
# Expose read access without exposing mutation.
return self.__balance
def deposit(self, amount):
# Keep validation next to the state it protects.
if amount <= 0:
raise ValueError("Amount must be positive")
self.__balance += amount
account = BankAccount(100)
account.deposit(50)
print(account.balance) # 150
Абстракция
Абстракция показывает полезный интерфейс и скрывает лишние детали.
from abc import ABC, abstractmethod
class PaymentMethod(ABC):
@abstractmethod
def pay(self, amount):
# Callers know what pay does, not how each provider does it.
pass
class CreditCard(PaymentMethod):
def pay(self, amount):
# The concrete class hides its payment implementation.
return f"Paid ${amount:.2f} by card"
payment = CreditCard()
print(payment.pay(25))
Наследование
Наследование специализирует класс только при настоящем отношении «является».
class Employee:
def __init__(self, name):
self.name = name
def describe(self):
return self.name
class Developer(Employee):
def __init__(self, name, language):
# Reuse initialization from the parent class.
super().__init__(name)
self.language = language
def describe(self):
# Extend inherited behavior instead of duplicating it.
return f"{super().describe()} writes {self.language}"
print(Developer("Ada", "Python").describe())
Полиморфизм
Полиморфизм применяет одну операцию к разным объектам с подходящим поведением.
class EmailNotification:
def send(self, message):
return f"Email: {message}"
class SmsNotification:
def send(self, message):
return f"SMS: {message}"
def notify(channels, message):
for channel in channels:
# The same call selects behavior from each concrete object.
print(channel.send(message))
channels = [EmailNotification(), SmsNotification()]
notify(channels, "Order shipped")
Как это работает
BankAccount инкапсулирует баланс. SavingsAccount наследует интерфейс и переопределяет month_end. Цикл одинаково работает с обоими объектами, а Python выбирает метод во время выполнения.
Измените значения и запустите программу в онлайн-компиляторе Python CodeUtility без локальной установки Python.
Практические задания
Изменяйте входные данные и проверяйте граничные случаи перед работой с большими наборами.
- Предскажите результат до запуска.
- Обработайте пустой и некорректный ввод.
- Вынесите логику в функцию и добавьте тесты.