💻 Примеры: итоговые сценарии
⚡ Кратко
Сначала запустите ключевые примеры без изменений, затем поменяйте входные данные и объясните получившийся результат.
Пример 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. Арифметические операторы
4.1. Сложение векторов
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.2. Инкрементный счётчик
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]))