Абстракция и полиморфизм в Python на примерах: код и задачи
Расскажем, для чего полиморфизм и абстракция используются в программировании, и как они взаимодействуют с остальными фундаментальными концепциями ООП. В конце статьи – решение 10 задач, связанных с абстрактными и полиморфными классами. ← Часть 18 Основы ООП – инкапсуляция и наследование Напомним, что эта статья – продолжение темы ООП в Python: предыдущая часть была посвящена инкапсуляции и наследованию. Одна из основных целей использования абстракции в ООП – повышение гибкости и упрощение разработки. Абстрактный подход помогает создавать интерфейсы и классы, которые определяют только те свойства и методы, которые необходимы для выполнения определенной задачи. Это позволяет создавать более гибкие и масштабируемые приложения, которые легко поддаются изменению и расширению. Предположим, что нам нужно написать программу, которая работает с графическими объектами разных типов. Для решения этой задачи удобно создать абстрактный класс Shape (фигура), определяющий абстрактные методы, которые могут быть использованы для работы с любой фигурой. Затем мы можем создать конкретные классы для конкретных типов фигур – окружность, квадрат, треугольник и т.д., которые расширяют базовый класс Shape. При этом мы можем использовать только те свойства и методы, которые необходимы для выполнения конкретной задачи, игнорируя детали реализации, которые не имеют значения в данном контексте. Абстрактный подход помогает эффективно решать ряд сложных задач: Для работы с абстрактными классами в Python используют модуль abc. Он предоставляет: Рассмотрим пример абстрактного класса Book: Класс Book имеет абстрактный метод get_summary(). Два подкласса Book (Fiction и NonFiction) реализуют метод get_summary(), а третий подкласс Poetry – нет. Когда мы создаем экземпляры Fiction и NonFiction и вызываем их методы get_summary(), получаем ожидаемый результат: Вывод: А вот вызов Poetry приведет к ошибке, поскольку в этом подклассе метод get_summary() не реализован: Вывод: Приведенный выше пример показывает, что семейство родственных классов (Fiction и NonFiction в нашем случае) может иметь общий интерфейс (метод get_summary()), но реализация этого интерфейса может быть разной. Мы также убедились, что любой подкласс Book должен реализовать метод get_summary(), чтобы обеспечить согласованную, безошибочную работу приложения. Теперь рассмотрим чуть более сложный пример, который продемонстрирует, как можно комбинировать абстракцию с другими концепциями ООП. Определим абстрактный класс Recipe (рецепт), который имеет абстрактный метод cook(). Затем создадим три подкласса Entree, Dessert и Appetizer (основное блюдо, десерт и закуска). Entree и Dessert имеют свои собственные методы cook(), в отличие от Appetizer и PartyMix. PartyMix (орешки, чипсы, крекеры) является подклассом Appetizer и имеет свою реализацию cook(): В этом примере наряду с абстракцией используются концепции полиморфизма и наследования. Наследование заключается в том, что подклассы Entree, Dessert и PartyMix наследуют абстрактный метод cook() от абстрактного базового класса Recipe. Это означает, что все они имеют ту же сигнатуру (название и параметры) метода cook(), что и абстрактный метод, определенный в классе Recipe. Полиморфизм проявляется в том, что каждый подкласс класса Recipe реализует метод cook() по-разному. Например, Entree реализует cook() для вывода инструкций по приготовлению основного блюда на медленном огне, а Dessert реализует cook() для вывода инструкций по смешиванию ингредиентов десерта. Эта разница в реализации является примером полиморфизма, когда различные объекты могут рассматриваться как объекты, которые относятся к одному типу, но при этом ведут себя по-разному: Результат: Вызов метода cook() для подкласса Appetizer приведет к ожидаемой ошибке: Результат: Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека питониста» Интересно, перейти к каналу Полиморфизм позволяет обращаться с объектами разных классов так, как будто они являются объектами одного класса. Реализовать полиморфизм можно через наследование, интерфейсы и перегрузку методов. Этот подход имеет несколько весомых преимуществ: Полиморфизм тесно связан с абстракцией: Таким образом, абстракция позволяет определить общий интерфейс для работы с объектами, а полиморфизм позволяет использовать этот интерфейс для работы с различными объектами, которые могут иметь различную реализацию. Рассмотрим полиморфизм на примере класса Confectionary (кондитерские изделия): В этом примере мы определяем базовый класс Confectionary, который имеет атрибуты name и price, а также метод describe(). Затем мы определяем три подкласса класса Confectionary: Cake, Candy и Cookie. Cake и Candy переопределяют метод describe() своими собственными реализациями, которые включают тип кондитерского изделия (торт и конфеты соответственно), а Cookie наследует дефолтный метод describe() от Confectionary. Если создать экземпляры этих классов и вызвать их методы describe(), можно убедиться, что результат зависит от реализации метода в каждом конкретном подклассе: Вывод: Теперь разберем на примере класса Beverage (напиток) взаимодействие полиморфизма с другими концепциями ООП. Beverage – родительский класс, который содержит: Soda (газировка) – дочерний класс Beverage, у него есть дополнительный атрибут flavor (вкус) и собственный метод describe(), включающий flavor. DietSoda – еще один дочерний класс Soda, который наследует все атрибуты и методы Soda, но переопределяет метод describe(), чтобы указать, что газировка является диетической: Этот пример демонстрирует: Вывод: В далекой-далекой галактике Федерация ведет ожесточенную войну с клингонами. Звездолеты Федерации оснащены мощными фазерами, а клингонские корабли – смертоносными фотонными торпедами. Обе стороны разработали усовершенствованные варп-двигатели для перемещения со сверхсветовой скоростью, и оборудовали свои корабли системами самоуничтожения на случай чрезвычайной ситуации. Для игры, посвященной этой войне, нужно создать абстрактный класс Starship с методами warp_speed(), fire_weapon() и self_destruct(). Кроме того, нужно создать два подкласса FederationStarship и KlingonWarship, которые наследуют абстрактные методы Starship и реализуют свои собственные версии методов warp_speed(), fire_weapon() и self_destruct(). Пример использования: Вывод: Решение: Для ПО ресторана нужно разработать модуль, помогающий контролировать использование фруктов и овощей на кухне. Создайте абстрактный класс Ingredient с методами get_name() и get_quantity(). Затем создайте два подкласса Vegetable и Fruit, которые наследуют абстрактные методы от Ingredient и реализуют свои собственные версии методов get_name() и get_quantity(). Пример использования: Вывод: Решение: Для военной стратегии необходимо создать абстрактный класс Soldier. Каждый солдат должен уметь двигаться, защищаться и атаковать, поэтому Soldier имеет три абстрактных метода: move(), attack() и defend(). Два конкретных класса, Infantry (пехота) и Cavalry (кавалерия), будут наследовать и реализовывать эти методы. В игре также должен быть класс Army, который будет добавлять солдат в армию и выполнять операции атаки и защиты. Чтобы гарантировать, что используются только экземпляры класса Soldier, нужно создать декоратор validatesoldier, который будет проверять тип объекта. Если объект не является экземпляром класса Soldier, декоратор выдаст ошибку Пример использования: Вывод: Решение: Палеонтологам, работающим в заповеднике для динозавров, понадобилось ПО для отслеживания множества травоядных и плотоядных подопечных. Данные, которые нужно учитывать по каждому динозавру – имя, вид, рост, вес и рацион питания. Создайте абстрактный класс Dinosaur с методами get_personal_name(), get_breed(), get_height(), get_weight() и get_diet(). Затем создайте два подкласса Carnivore (плотоядный) и Herbivore (травоядный), которые наследуют методы Dinosaur и реализуют свои собственные версии get_personal_name(), get_breed(), get_height(), get_weight() и get_diet(). Кроме того, создайте класс DinosaurPark, который содержит список динозавров и имеет методы list_dinosaurs(), list_carnivores() и list_herbivores() для вывода списков a) всех динозавров, b) плотоядных и c) травоядных особей. Пример использования: Вывод: Решение: Для учета музыкальных инструментов в оркестре нужно создать абстрактный класс Instrument с методами get_name(), get_type(), get_sound() и play(). Два подкласса StringedInstrument (струнные) и PercussionInstrument (ударные) наследуют методы Instrument и реализуют свои собственные версии методов get_name(), get_type(), get_sound() и play(). Кроме того, необходимо реализовать класс Orchestra: он добавляет новые инструменты и имеет методы list_instruments(), list_stringed_instruments(), list_percussion_instruments(), которые выводят списки a) всех инструментов, b) ударных, c) струнных. Пример использования: Вывод: Решение: Напишите класс FilmCatalogue (каталог фильмов), который отвечает за ведение фильмотеки. FilmCatalogue должен поддерживать различные типы кинокартин, чтобы пользователи могли искать фильмы по определенному жанру. Для этого необходимо создать новые классы для различных жанров (например, Horror, Action, Romance), которые наследуют класс Movie и переопределяют метод play() для вывода информации о том, к какому жанру относится фильм. Пример использования: Вывод: Решение: Для CRM винодельни нужно написать модуль, отвечающий за учет красных, белых и розовых вин, каждое из которых имеет свое название, сорт винограда, год и температуру подачи. Создайте базовый класс Wine с атрибутами name, grape и year. Затем создайте три подкласса RedWine, WhiteWine и RoseWine, которые наследуют методы и атрибуты от Wine и реализуют свои собственные версии метода serve(). Кроме того, создайте класс Winery, который ведет список вин и имеет метод serve_wines(), вызывающий метод serve() для каждого вина. Пример использования: Вывод: Решение: Для ПО аэропорта нужно разработать модуль, отслеживающий пассажирские и грузовые самолеты, которые отличаются моделью, производителем, вместимостью и грузоподъемностью. Создайте базовый класс Aircraft (воздушное судно) с атрибутами model, manufacturer и capacity. Затем создайте два подкласса PassengerAircraft и CargoAircraft, которые наследуют атрибуты и методы от Aircraft и реализуют свои собственные версии метода fly(). В дополнение создайте класс Airport, который содержит список самолетов и имеет метод takeoff(), вызывающий метод fly() для каждого самолета. Пример использования: Вывод: Решение: Необходимо реализовать модуль, отвечающий за обработку данных о тестировании конфигурации настольных компьютеров и ноутбуков, каждый из которых отличается моделью, процессором, памятью и производительностью. Создайте базовый класс Computer с атрибутами model, processor и memory. Затем создайте два подкласса Desktop и Laptop, которые наследуют атрибуты и методы Computer и реализуют свои собственные версии метода run(). В дополнение, создайте класс ComputerStore, который содержит список компьютеров и имеет метод run_tests(), вызывающий метод run() для каждого компьютера. Используйте декораторы для вывода результатов. Пример использования: Вывод: Решение: Определите базовый класс Cryptocurrency, имеющий атрибуты: Затем создайте три подкласса Nano, Iota и Stellar, которые наследуют атрибуты и методы родительского класса Cryptocurrency, и обладают дополнительными свойствами, влияющими на размер вознаграждения за майнинг: Кроме того, нужно реализовать: Пример использования: Вывод: Решение: Объектно-ориентированный подход обладает несколькими важными преимуществами, среди которых: В следующей части будем изучать основы разработки приложений с графическим интерфейсом. *** Абстракция
Абстрактные классы в Python
from abc import ABC, abstractmethod class Book(ABC): def __init__(self, title, author): self.title = title self.author = author @abstractmethod def get_summary(self): pass class Fiction(Book): def get_summary(self): print(f'"{self.title}" - роман в стиле исторический фикшн, автор - {self.author}') class NonFiction(Book): def get_summary(self): print(f'"{self.title}" - книга в стиле нон фикшн, автор - {self.author}') class Poetry(Book): pass
fiction_book = Fiction("Террор", "Дэн Симмонс") nonfiction_book = NonFiction("Как писать книги", "Стивен Кинг") fiction_book.get_summary() nonfiction_book.get_summary()
"Террор" - роман в стиле исторический фикшн, автор - Дэн Симмонс "Как писать книги" - книга в стиле нон фикшн, автор - Стивен Кинг
poetry_book = Poetry("Стихотворения", "Борис Пастернак")
TypeError: Can't instantiate abstract class Poetry with abstract methods get_summary
from abc import ABC, abstractmethod class Recipe(ABC): @abstractmethod def cook(self): pass class Entree(Recipe): def __init__(self, ingredients): self.ingredients = ingredients def cook(self): print(f"Готовим на медленном огне смесь ингредиентов ({', '.join(self.ingredients)}) для основного блюда") class Dessert(Recipe): def __init__(self, ingredients): self.ingredients = ingredients def cook(self): print(f"Смешиваем {', '.join(self.ingredients)} для десерта") class Appetizer(Recipe): pass class PartyMix(Appetizer): def cook(self): print("Готовим снеки - выкладываем на поднос орешки, чипсы и крекеры")
entree = Entree(["курица", "рис", "овощи"]) dessert = Dessert(["мороженое", "шоколадные чипсы", "мараскиновые вишни"]) partymix = PartyMix() entree.cook() dessert.cook() partymix.cook()
Готовим на медленном огне смесь ингредиентов (курица, рис, овощи) для основного блюда Смешиваем мороженое, шоколадные чипсы, мараскиновые вишни для десерта Готовим снеки - выкладываем на поднос орешки, чипсы и крекеры
appetizer = Appetizer() appetizer.cook()
TypeError: Can't instantiate abstract class Appetizer with abstract methods cook
Полиморфизм
class Confectionary: def __init__(self, name, price): self.name = name self.price = price def describe(self): print(f"{self.name} по цене {self.price} руб/кг") class Cake(Confectionary): def describe(self): print(f"{self.name} торт стоит {self.price} руб/кг") class Candy(Confectionary): def describe(self): print(f"{self.name} конфеты стоимостью {self.price} руб/кг") class Cookie(Confectionary): pass
cake = Cake("Пражский", 1200) candy = Candy("Шоколадные динозавры", 560) cookie = Cookie("Овсяное печенье с миндалем", 250) cake.describe() candy.describe() cookie.describe()
Пражский торт стоит 1200 руб/кг Шоколадные динозавры конфеты стоимостью 560 руб/кг Овсяное печенье с миндалем по цене 250 руб/кг
class Beverage: def __init__(self, name, size, price): self._name = name self._size = size self._price = price def get_name(self): return self._name def get_size(self): return self._size def get_price(self): return self._price def set_price(self, price): self._price = price def describe(self): return f'{self._size} л газировки "{self._name}" стоит {self._price} руб.' class Soda(Beverage): def __init__(self, name, size, price, flavor): super().__init__(name, size, price) self._flavor = flavor def get_flavor(self): return self._flavor def describe(self): return f'{self._size} л газировки "{self._name}" со вкусом "{self._flavor}" стоит {self._price} руб.' class DietSoda(Soda): def __init__(self, name, size, price, flavor): super().__init__(name, size, price, flavor) def describe(self): return f'{self._size} л диетической газировки "{self._name}" со вкусом "{self._flavor}" стоит {self._price} руб.' regular_soda = Soda('Sprite', 0.33, 45, 'лимон') print(regular_soda.describe()) diet_soda = DietSoda('Mirinda', 0.33, 50, 'мандарин') print(diet_soda.describe()) regular_soda = Soda('Буратино', 1.5, 65, 'дюшес') print(regular_soda.describe())
0.33 л газировки "Sprite" со вкусом "лимон" стоит 45 руб. 0.33 л диетической газировки "Mirinda" со вкусом "мандарин" стоит 50 руб. 1.5 л газировки "Буратино" со вкусом "дюшес" стоит 65 руб.
Практика
Задание 1
enterprise = FederationStarship() bird_of_prey = KlingonWarship() enterprise.warp_speed() bird_of_prey.warp_speed() enterprise.fire_weapon() bird_of_prey.fire_weapon() enterprise.self_destruct() bird_of_prey.self_destruct()
Включить варп-двигатели! Включить маскировочное устройство! Выпустить фотонные торпеды! Стрелять из фазеров! Запускаю систему самоуничтожения... Запускаю протокол самоуничтожения...
from abc import ABC, abstractmethod class Starship(ABC): @abstractmethod def warp_speed(self): pass @abstractmethod def fire_weapon(self): pass @abstractmethod def self_destruct(self): pass class FederationStarship(Starship): def warp_speed(self): print("Включить варп-двигатели!") def fire_weapon(self): print("Выпустить фотонные торпеды!") def self_destruct(self): print("Запускаю систему самоуничтожения...") class KlingonWarship(Starship): def warp_speed(self): print("Включить маскировочное устройство!") def fire_weapon(self): print("Стрелять из фазеров!") def self_destruct(self): print("Запускаю протокол самоуничтожения...")
Задание 2
carrot = Vegetable("Морковь", 5) apple = Fruit("Яблоки", 10) print(carrot.get_name()) print(carrot.get_quantity()) print(apple.get_name()) print(apple.get_quantity())
Морковь 5 кг Яблоки 10 кг
from abc import ABC, abstractmethod class Ingredient(ABC): @abstractmethod def get_name(self): pass @abstractmethod def get_quantity(self): pass class Vegetable(Ingredient): def __init__(self, name, quantity): self.name = name self.quantity = quantity def get_name(self): return self.name def get_quantity(self): return f'{self.quantity} кг' class Fruit(Ingredient): def __init__(self, name, quantity): self.name = name self.quantity = quantity def get_name(self): return self.name def get_quantity(self): return f'{self.quantity} кг'
Задание 3
TypeError
. Декоратор будет применяться к методам move(), attack() и defend() классов Infantry и Cavalry.
army = Army() army.add_soldier(Infantry()) army.add_soldier(Cavalry()) army.add_soldier(Infantry()) army.add_soldier(Cavalry()) army.attack() army.defend()
Пехота передвигается в пешем порядке Пехота участвует в ближнем бою Кавалерия передвигается верхом Кавалерия переходит в атаку Пехота передвигается в пешем порядке Пехота участвует в ближнем бою Кавалерия передвигается верхом Кавалерия переходит в атаку Пехота передвигается в пешем порядке Пехота держит строй Кавалерия передвигается верхом Кавалерия защищает фланги Пехота передвигается в пешем порядке Пехота держит строй Кавалерия передвигается верхом Кавалерия защищает фланги
from abc import ABC, abstractmethod def validate_soldier(func): def wrapper(self): if not isinstance(self, Soldier): raise TypeError("Объект не является экземпляром Soldier") return func(self) return wrapper class Soldier(ABC): @abstractmethod def move(self): pass @abstractmethod def attack(self): pass @abstractmethod def defend(self): pass class Infantry(Soldier): @validate_soldier def move(self): print("Пехота передвигается в пешем порядке") @validate_soldier def attack(self): print("Пехота участвует в ближнем бою") @validate_soldier def defend(self): print("Пехота держит строй") class Cavalry(Soldier): @validate_soldier def move(self): print("Кавалерия передвигается верхом") @validate_soldier def attack(self): print("Кавалерия переходит в атаку") @validate_soldier def defend(self): print("Кавалерия защищает фланги") class Army: def __init__(self): self.soldiers = [] def add_soldier(self, soldier): self.soldiers.append(soldier) def attack(self): for soldier in self.soldiers: soldier.move() soldier.attack() def defend(self): for soldier in self.soldiers: soldier.move() soldier.defend()
Задание 4
t_rex = Carnivore('Тираннозавр', 'Рекс', 4800, 560) velociraptor = Carnivore('Велоцираптор', 'Зубастик', 30, 70) stegosaurus = Herbivore('Стегозавр', 'Стегга', 7100, 420) triceratops = Herbivore('Трицератопс', 'Трипси', 8000, 290) park = DinosaurPark() park.add_dinosaur(t_rex) park.add_dinosaur(velociraptor) park.add_dinosaur(stegosaurus) park.add_dinosaur(triceratops) for dinosaur in park.list_dinosaurs(): print(f'Имя: {dinosaur[0]}n' f'Вид: {dinosaur[1]}n' f'Вес: {dinosaur[2]} кгn' f'Рост: {dinosaur[3]} смn' f'Рацион: {dinosaur[4]}n')
Имя: Рекс Вид: Тираннозавр Вес: 4800 кг Рост: 560 см Рацион: Плотоядный Имя: Зубастик Вид: Велоцираптор Вес: 30 кг Рост: 70 см Рацион: Плотоядный Имя: Стегга Вид: Стегозавр Вес: 7100 кг Рост: 420 см Рацион: Травоядный Имя: Трипси Вид: Трицератопс Вес: 8000 кг Рост: 290 см Рацион: Травоядный
from abc import ABC, abstractmethod class Dinosaur(ABC): @abstractmethod def get_personal_name(self): pass @abstractmethod def get_breed(self): pass @abstractmethod def get_height(self): pass @abstractmethod def get_weight(self): pass @abstractmethod def get_diet(self): pass class Carnivore(Dinosaur): def __init__(self, breed, personal_name, height, weight): self.breed = breed self.personal_name = personal_name self.height = height self.weight = weight def get_personal_name(self): return self.personal_name def get_breed(self): return self.breed def get_height(self): return self.height def get_weight(self): return self.weight def get_diet(self): return 'Плотоядный' class Herbivore(Dinosaur): def __init__(self, breed, personal_name, height, weight): self.breed = breed self.personal_name = personal_name self.height = height self.weight = weight def get_personal_name(self): return self.personal_name def get_breed(self): return self.breed def get_height(self): return self.height def get_weight(self): return self.weight def get_diet(self): return 'Травоядный' class DinosaurPark: def __init__(self): self.dinosaurs = [] def add_dinosaur(self, dinosaur): self.dinosaurs.append(dinosaur) def list_dinosaurs(self): return [(dinosaur.get_personal_name(), dinosaur.get_breed(), dinosaur.get_height(), dinosaur.get_weight(), dinosaur.get_diet()) for dinosaur in self.dinosaurs] def list_carnivores(self): return [(dinosaur.get_personal_name(), dinosaur.get_breed(), dinosaur.get_height(), dinosaur.get_weight()) for dinosaur in self.dinosaurs if isinstance(dinosaur, Carnivore)] def list_herbivores(self): return [(dinosaur.get_personal_name(), dinosaur.get_breed(), dinosaur.get_height(), dinosaur.get_weight()) for dinosaur in self.dinosaurs if isinstance(dinosaur, Herbivore)]
Задание 5
chello = StringedInstrument("виолончель", "струнный инструмент", "Strum") maracas = PercussionInstrument("маракасы", "ударный инструмент", "Maracas") violin = StringedInstrument("скрипка", "струнный инструмент", "Virtuso") drums = PercussionInstrument("барабан", "ударный инструмент", "Beat") orchestra = Orchestra() orchestra.add_instrument(chello) orchestra.add_instrument(maracas) orchestra.add_instrument(violin) orchestra.add_instrument(drums) print("В оркестрe есть инструменты:", ', '.join(orchestra.list_instruments())) print("Струнные инструменты:", ', '.join(orchestra.list_stringed_instruments())) print("Ударные инструменты:", ', '.join(orchestra.list_percussion_instruments())) print(chello.play()) print(drums.play())
В оркестрe есть инструменты: виолончель, маракасы, скрипка, барабан Струнные инструменты: виолончель, скрипка Ударные инструменты: маракасы, барабан Звучит струнный инструмент виолончель Звучит ударный инструмент барабан
from abc import ABC, abstractmethod def print_decorator(func): def wrapper(*args, **kwargs): result = func(*args, **kwargs) return result return wrapper class Instrument(ABC): @abstractmethod def get_name(self): pass @abstractmethod def get_type(self): pass @abstractmethod def get_sound(self): pass @abstractmethod def play(self): pass class StringedInstrument(Instrument): def __init__(self, name, type, sound): self.name = name self.type = type self.sound = sound def get_name(self): return self.name def get_type(self): return self.type def get_sound(self): return self.sound def play(self): return f"Звучит {self.type} {self.name}" class PercussionInstrument(Instrument): def __init__(self, name, type, sound): self.name = name self.type = type self.sound = sound def get_name(self): return self.name def get_type(self): return self.type def get_sound(self): return self.sound def play(self): return f"Звучит {self.type} {self.name}" class Orchestra: def __init__(self): self.instruments = [] def add_instrument(self, instrument): self.instruments.append(instrument) @print_decorator def list_instruments(self): return [instrument.get_name() for instrument in self.instruments] @print_decorator def list_stringed_instruments(self): return [instrument.get_name() for instrument in self.instruments if isinstance(instrument, StringedInstrument)] @print_decorator def list_percussion_instruments(self): return [instrument.get_name() for instrument in self.instruments if isinstance(instrument, PercussionInstrument)]
Задание 6
my_catalogue = FilmCatalogue() my_catalogue.add_movie(Drama("Крестный отец", "Френсис Ф. Коппола")) my_catalogue.add_movie(Comedy("Ночные игры", "Джон Фрэнсис Дейли, Джонатан М. Голдштейн")) my_catalogue.add_movie(Horror("Дракула Брэма Стокера", "Френсис Ф. Коппола")) my_catalogue.add_movie(Action("Крушение", "Жан-Франсуа Рише")) my_catalogue.add_movie(Romance("Честная куртизанка", "Маршалл Херсковиц")) my_catalogue.play_all_movies() print(f"nНайдены фильмы ужасов:") for movie in my_catalogue.search_movies_by_genre(Horror): print(movie.title) print(f"nЗапускаем фильм из жанра 'Мелодрамы':") my_catalogue.play_movies_by_genre(Romance)
Включаем драму 'Крестный отец' реж. Френсис Ф. Коппола. Включаем комедию 'Ночные игры' реж. Джон Фрэнсис Дейли, Джонатан М. Голдштейн. Включаем фильм ужасов 'Дракула Брэма Стокера' реж. Френсис Ф. Коппола. Включаем боевик 'Крушение' реж. Жан-Франсуа Рише. Включаем мелодраму 'Честная куртизанка' реж. Маршалл Херсковиц. Найдены фильмы ужасов: Дракула Брэма Стокера Запускаем фильм из жанра 'Мелодрамы': Включаем мелодраму 'Честная куртизанка' реж. Маршалл Херсковиц.
class Movie: def __init__(self, title, director): self.title = title self.director = director def play(self): print(f"Собираемся смотреть фильм '{self.title}' реж. {self.director}.") class Comedy(Movie): def play(self): print(f"Включаем комедию '{self.title}' реж. {self.director}.") class Drama(Movie): def play(self): print(f"Включаем драму '{self.title}' реж. {self.director}.") class Horror(Movie): def play(self): print(f"Включаем фильм ужасов '{self.title}' реж. {self.director}.") class Action(Movie): def play(self): print(f"Включаем боевик '{self.title}' реж. {self.director}.") class Romance(Movie): def play(self): print(f"Включаем мелодраму '{self.title}' реж. {self.director}.") class FilmCatalogue: def __init__(self): self.movies = [] def add_movie(self, movie): self.movies.append(movie) def play_all_movies(self): for movie in self.movies: movie.play() def search_movies_by_genre(self, genre): return [movie for movie in self.movies if isinstance(movie, genre)] def play_movies_by_genre(self, genre): movies = self.search_movies_by_genre(genre) for movie in movies: movie.play()
Задание 7
winery = Winery() winery.add_wine(RedWine("Cabernet Sauvignon", "Каберне Совиньон", 2015)) winery.add_wine(WhiteWine("Chardonnay", "Шардоне", 2018)) winery.add_wine(RoseWine("Grenache", "Гренаш", 2020)) winery.serve_wines()
Красное вино 'Cabernet Sauvignon', сделанное из винограда сорта Каберне Совиньон в 2015 году, рекомендуем подавать комнатной температуры. Белое вино 'Chardonnay', сделанное из винограда сорта Шардоне в 2018 году, рекомендуем подавать хорошо охлажденным. Розовое вино 'Grenache', сделанное из винограда сорта Гренаш в 2020 году, рекомендуем подавать слегка охлажденным.
class Wine: def __init__(self, name, grape, year): self.name = name self.grape = grape self.year = year class RedWine(Wine): def serve(self): print(f"Красное вино '{self.name}', сделанное из винограда сорта {self.grape} в {self.year} году, рекомендуем подавать комнатной температуры.") class WhiteWine(Wine): def serve(self): print(f"Белое вино '{self.name}', сделанное из винограда сорта {self.grape} в {self.year} году, рекомендуем подавать хорошо охлажденным.") class RoseWine(Wine): def serve(self): print(f"Розовое вино '{self.name}', сделанное из винограда сорта {self.grape} в {self.year} году, рекомендуем подавать слегка охлажденным.") class Winery: def __init__(self): self.wines = [] def add_wine(self, wine): self.wines.append(wine) def serve_wines(self): for wine in self.wines: wine.serve()
Задание 8
airport = Airport() airport.add_aircraft(PassengerAircraft("Boeing 747", "Боинг", 416)) airport.add_aircraft(CargoAircraft("Airbus A330", "Эйрбас", 70)) airport.add_aircraft(PassengerAircraft("Boeing 777", "Боинг", 396)) airport.takeoff()
Пассажирский самолет 'Boeing 747' вместимостью 416 человек, произведенный компанией Боинг, поднимается в воздух с пассажирами на борту. Грузовой самолет 'Airbus A330' с грузоподъемностью 70 т, произведенный компанией Эйрбас, поднимается в воздух с грузом на борту. Пассажирский самолет 'Boeing 777' вместимостью 396 человек, произведенный компанией Боинг, поднимается в воздух с пассажирами на борту.
class Aircraft: def __init__(self, model, manufacturer, capacity): self.model = model self.manufacturer = manufacturer self.capacity = capacity class PassengerAircraft(Aircraft): def fly(self): print(f"Пассажирский самолет '{self.model}' вместимостью {self.capacity} человек, произведенный компанией {self.manufacturer}, поднимается в воздух с пассажирами на борту.") class CargoAircraft(Aircraft): def fly(self): print(f"Грузовой самолет '{self.model}' с грузоподъемностью {self.capacity} т, произведенный компанией {self.manufacturer}, поднимается в воздух с грузом на борту.") class Airport: def __init__(self): self.aircrafts = [] def add_aircraft(self, aircraft): self.aircrafts.append(aircraft) def takeoff(self): for aircraft in self.aircrafts: aircraft.fly()
Задание 9
store = ComputerStore() store.add_computer(Desktop("HP Legion", "Intel Core i9-10900K", "64 Гб")) store.add_computer(Laptop("Dell Xtra", "Intel Core i5 13600K", "32 Гб")) store.add_computer(Desktop("Lenovo SuperPad", "AMD Ryzen 7 2700X", "16 Гб")) store.run_tests()
Начинаем тест производительности... Запускаем настольный компьютер 'HP Legion' с процессором Intel Core i9-10900K и 64 Гб RAM. Тест производительности завершен. Начинаем тест производительности... Запускаем ноутбук 'Dell Xtra' с процессором Intel Core i5 13600K и 32 Гб RAM. Тест производительности завершен. Начинаем тест производительности... Запускаем настольный компьютер 'Lenovo SuperPad' с процессором AMD Ryzen 7 2700X и 16 Гб RAM. Тест производительности завершен.
def performance_test(func): def wrapper(*args, **kwargs): print("Начинаем тест производительности...") result = func(*args, **kwargs) print("Тест производительности завершен.") return result return wrapper class Computer: def __init__(self, model, processor, memory): self.model = model self.processor = processor self.memory = memory @performance_test def run(self): pass class Desktop(Computer): @performance_test def run(self): print(f"Запускаем настольный компьютер '{self.model}' с процессором {self.processor} и {self.memory} RAM.") class Laptop(Computer): @performance_test def run(self): print(f"Запускаем ноутбук '{self.model}' с процессором {self.processor} и {self.memory} RAM.") class ComputerStore: def __init__(self): self.computers = [] def add_computer(self, computer): self.computers.append(computer) def run_tests(self): for computer in self.computers: computer.run()
Задание 10
cryptocurrencies = [Nano(block_lattice=True, rate_to_usd=6, anonymous=False), Iota(tangle=True, rate_to_usd=0.4, anonymous=False), Stellar(distributed=False, rate_to_usd=0.15, anonymous=True)] for crypto in cryptocurrencies: print_info(crypto) if crypto.minable: print(f"Награда за майнинг: {crypto.mining_reward()} {crypto.symbol}n")
Nano (NANO): добывают майнингом, курс к USD: 6, только публичные транзакции, блок-решетка Награда за майнинг: 0.02 NANO Iota (IOTA): добывают майнингом, курс к USD: 0.4, только публичные транзакции Награда за майнинг: 0.001 IOTA Stellar (XLM): не майнится, курс к USD: 0.15, анонимные транзакции
class Cryptocurrency: def __init__(self, name, symbol, minable=True, rate_to_usd=1, anonymous=False): self.name = name self.symbol = symbol self.minable = minable self.rate_to_usd = rate_to_usd self.anonymous = anonymous def __str__(self): return f"{self.name} ({self.symbol})" def mining_reward(self): return None def minable_required(func): def wrapper(crypto): if not crypto.minable: print("Эту криптовалюту не майнят") return None return func(crypto) return wrapper class Nano(Cryptocurrency): def __init__(self, block_lattice=False, rate_to_usd=5, anonymous=True): super().__init__("Nano", "NANO", True, rate_to_usd, anonymous) self.block_lattice = block_lattice @minable_required def mining_reward(self): return 0.02 if self.block_lattice else 0.01 class Iota(Cryptocurrency): def __init__(self, tangle=False, rate_to_usd=0.3, anonymous=False): super().__init__("Iota", "IOTA", True, rate_to_usd, anonymous) self.tangle = tangle @minable_required def mining_reward(self): return 0.001 if self.tangle else 0.002 class Stellar(Cryptocurrency): def __init__(self, distributed=False, rate_to_usd=0.1, anonymous=True): super().__init__("Stellar", "XLM", False, rate_to_usd, anonymous) self.distributed = distributed def mining_reward(self): print("Stellar is not minable") return None def print_info(crypto): minable_str = 'добывают майнингом' if crypto.minable else 'не майнится' anonymity_str = 'анонимные транзакции' if crypto.anonymous else 'только публичные транзакции' block_lattice_str = 'блок-решетка' if hasattr(crypto, 'block_lattice') and crypto.block_lattice else '' if block_lattice_str: print(f"{crypto}: {minable_str}, курс к USD: {crypto.rate_to_usd}, {anonymity_str}, {block_lattice_str}") else: print(f"{crypto}: {minable_str}, курс к USD: {crypto.rate_to_usd}, {anonymity_str}")
Подведем итоги
Содержание самоучителя
- 0 views
- 0 Comment