💻 Примеры: итоговые сценарии

⚡ Кратко

Сначала запустите ключевые примеры без изменений, затем поменяйте входные данные и объясните получившийся результат.

Пример 1. Миксины с hasattr

class AuthMixin:
    def login(self) -> None:
        if not hasattr(self, "username"):
            raise AttributeError("Не задан username")
        print(f"{self.username} вошёл в систему.")

    def logout(self) -> None:
        print("Пользователь вышел из системы.")


class NotificationMixin:
    def send_email(self, message: str) -> None:
        if not hasattr(self, "email"):
            raise AttributeError("Не задан email")
        print(f"Отправка письма на {self.email}: {message}")


class UserProfile(AuthMixin, NotificationMixin):
    def __init__(self, username: str, email: str) -> None:
        self.username = username
        self.email = email


user = UserProfile("alice", "alice@example.com")
user.login()
user.send_email("Добро пожаловать!")
user.logout()

Пример 2. MRO и super()

class A:
    def action(self) -> None:
        print("A")


class B(A):
    def action(self) -> None:
        print("B")
        super().action()


class C(A):
    def action(self) -> None:
        print("C")
        super().action()


class D(B, C):
    def action(self) -> None:
        print("D")
        super().action()


print(D.__mro__)
d = D()
d.action()

Вывод: D B C A.

Пример 3. Композиция

class Battery:
    def __init__(self, capacity: int) -> None:
        self.capacity = capacity
        self.charge = capacity

    def use(self, amount: int) -> None:
        self.charge = max(self.charge - amount, 0)
        print(f"Батарея: {self.charge}/{self.capacity} мАч")


class Smartphone:
    def __init__(self, model: str, battery_capacity: int) -> None:
        self.model = model
        self.__battery = Battery(battery_capacity)

    def play_video(self) -> None:
        print(f"{self.model} воспроизводит видео...")
        self.__battery.use(300)


phone = Smartphone("Pixel 9", 4000)
phone.play_video()

Пример 4. Инкапсуляция через @property

class BankAccount:
    def __init__(self, owner: str, balance: float = 0) -> None:
        self.owner = owner
        self.__balance = balance
        self.__history: list[str] = []

    def deposit(self, amount: float) -> None:
        if amount <= 0:
            raise ValueError("Сумма должна быть положительной")
        self.__balance += amount
        self.__history.append(f"Deposit: {amount}")

    def withdraw(self, amount: float) -> None:
        if amount <= 0:
            raise ValueError("Сумма должна быть положительной")
        if amount > self.__balance:
            raise ValueError("Недостаточно средств")
        self.__balance -= amount
        self.__history.append(f"Withdraw: {amount}")

    @property
    def balance(self) -> float:
        return self.__balance

    @property
    def history(self) -> list[str]:
        return self.__history.copy()


account = BankAccount("Alice")
account.deposit(150)
account.withdraw(100)
print(account.balance)
print(account.history)