""" Урок 79. Summary session 20 — весь код примеров одним файлом. Источник: subjects/python-fundamentals/course/lessons/79-summary-session-20/examples.html Файл собран автоматически (tools/build_lesson_examples.py): правьте страницу урока. Запуск: python lesson-79.py """ # ==================================================================== # Пример 1. Абстрактный класс # ==================================================================== from abc import ABC, abstractmethod class Employee(ABC): """Абстрактный базовый класс для сотрудников.""" @abstractmethod def work(self) -> None: """Основная деятельность сотрудника.""" pass def take_break(self) -> None: print("Перерыв на кофе.") class Programmer(Employee): def work(self) -> None: print("Пишу код.") class Manager(Employee): def work(self) -> None: print("Планирую задачи.") if __name__ == "__main__": for person in (Programmer(), Manager()): person.work() person.take_break() # ==================================================================== # Пример 2. Пользовательское исключение с дополнительным полем # ==================================================================== class AccessDeniedError(Exception): """Вызывается, если возраст недостаточен для доступа.""" def __init__(self, age: int): self.age = age super().__init__(f"Access denied: age {age} is too low") def check_age(age: int) -> None: if age < 18: raise AccessDeniedError(age) print("Access granted") if __name__ == "__main__": try: check_age(15) except AccessDeniedError as e: print("Error:", e) print("Age:", e.age) # ==================================================================== # Пример 3. Контейнер с магическими методами # ==================================================================== class Notes: """Коллекция заметок с ключами в нижнем регистре.""" def __init__(self) -> None: self._data: dict[str, str] = {} def __getitem__(self, key: str) -> str: return self._data[key.lower()] def __setitem__(self, key: str, value: str) -> None: if not value.strip(): raise ValueError("Empty notes are not allowed") self._data[key.lower()] = value def __contains__(self, key: str) -> bool: return key.lower() in self._data def __len__(self) -> int: return len(self._data) def __str__(self) -> str: lines = [f"- {k}: {v}" for k, v in self._data.items()] return "Notes:\n" + "\n".join(lines) if __name__ == "__main__": notes = Notes() notes["Idea"] = "Build a game" notes["TODO"] = "Finish the project" print(notes["idea"]) print("todo" in notes) print(len(notes)) print(notes) # ==================================================================== # Пример 4. Арифметические операторы # ==================================================================== class Vector: def __init__(self, x: float, y: float) -> None: self.x = x self.y = y def __add__(self, other: "Vector") -> "Vector": if not isinstance(other, Vector): return NotImplemented return Vector(self.x + other.x, self.y + other.y) def __str__(self) -> str: return f"({self.x}, {self.y})" if __name__ == "__main__": a = Vector(2, 3) b = Vector(1, 4) print(a + b) # ==================================================================== # Пример 4. Арифметические операторы # ==================================================================== class Counter: def __init__(self, value: int = 0) -> None: self.value = value def __iadd__(self, other: int) -> "Counter": self.value += other return self def __str__(self) -> str: return f"Counter({self.value})" if __name__ == "__main__": c = Counter(5) c += 3 print(c) # ==================================================================== # Пример 5. __call__ и __bool__ # ==================================================================== class CurrencyConverter: """Объект-конвертер валют.""" def __init__(self, rate: float) -> None: self.rate = rate def __call__(self, dollars: float) -> float: return dollars * self.rate class Counter: def __init__(self, value: int) -> None: self.value = value def __bool__(self) -> bool: return self.value > 0 if __name__ == "__main__": euro = CurrencyConverter(0.88) print(euro(10)) print(euro(5.5)) c1 = Counter(-5) c2 = Counter(3) print(bool(c1), bool(c2)) if c2: print("Есть элементы") if not c1: print("Пусто") # ==================================================================== # Пример 6. Сравнение через @total_ordering # ==================================================================== from functools import total_ordering @total_ordering class Book: def __init__(self, title: str) -> None: self.title = title def __eq__(self, other: object) -> bool: if not isinstance(other, Book): return NotImplemented return self.title == other.title def __lt__(self, other: "Book") -> bool: return self.title < other.title def __repr__(self) -> str: return f"Book({self.title!r})" if __name__ == "__main__": b1 = Book("1984") b2 = Book("1984") b3 = Book("Brave New World") print(b1 == b2) print(b1 < b3) print(b1 >= b3) print(sorted([b3, b1, b2]))