Share This
Связаться со мной
Крути в низ
Categories
//Инкапсуляция и наследование в Python на примерах: код и задачи

Инкапсуляция и наследование в Python на примерах: код и задачи

Рассмотрим базовые понятия (классы, подклассы и методы) и приступим к изучению первых двух фундаментальных принципов объектно-ориентированного программирования. В конце статьи – 10 заданий, связанных с инкапсуляцией и наследованием.

inkapsuljacija i nasledovanie v python na primerah kod i zadachi a96b12c - Инкапсуляция и наследование в Python на примерах: код и задачи

← Часть 17 Основы скрапинга и парсинга

Объектно-ориентированное программирование (ООП) – это парадигма программирования, в которой для представления данных и для проведения операций над этими данными используются объекты.

Объекты, в свою очередь, являются экземплярами классов – с этой точки зрения классы можно назвать шаблонами для создания объектов определенного типа. Классы определяют:

  • структуру данных, которые характеризуют объект;
  • свойства (атрибуты) и статус (состояние) объекта;
  • операции, которые можно совершать с данными объекта (методы).

В этом примере класс Car (автомобиль) имеет атрибуты make, model, year (марка, модель, год выпуска):

         class Car:     def __init__(self, make, model, year):         self.make = make         self.model = model         self.year = year      

Атрибуты – это свойства, характеристики объекта. Они определяют качества и состояние объекта. Атрибуты объекта перечисляют внутри __init__ метода класса – он вызывается каждый раз при создании экземпляра класса. Параметр self создает ссылку на экземпляр класса и позволяет получить доступ к атрибутам и методам объекта. Для создания экземпляра Car достаточно вызвать класс, передавая в скобках значения, соответствующие его атрибутам:

         my_car = Car("Toyota", "Corolla", 2023)     

Теперь, когда атрибутам объекта присвоены значения, можно к ним обращаться – для этого используют выражение название_объекта.атрибут:

         print(f'Марка машины {my_car.make},'       f'nмодель {my_car.model},'       f'nгод выпуска - {my_car.year}'       )      
         Результат: Марка машины Toyota, модель Corolla, год выпуска – 2023      

Car – пример простейшего класса: у него нет ни подклассов, ни методов, кроме обязательного __init__. Метод – это функция, которая определяет поведение объекта. Проиллюстрируем создание метода на примере класса WashingMachine – здесь метод remaining_warranty_time() определяет срок истечения гарантии на стиральную машину:

         import datetime  class WashingMachine:     def __init__(self, brand, model, purchase_date, warranty_length):         self.brand = brand         self.model = model         self.purchase_date = purchase_date         self.warranty_length = warranty_length      def remaining_warranty_time(self):         today = datetime.date.today()         warranty_end_date = self.purchase_date + datetime.timedelta(days=self.warranty_length)         remaining_time = warranty_end_date - today         if remaining_time.days < 0:             return "Срок действия гарантии истек."         else:             return "Срок действия гарантии истекает через {} дней.".format(remaining_time.days)  # создаем объект стиральной машины my_washing_machine = WashingMachine("LG", "FH4U2VCN2", datetime.date(2022, 5, 7), 1550)  # вызываем метод для проверки срока истечения гарантии print(my_washing_machine.remaining_warranty_time())      

Результат:

         Срок действия гарантии истекает через 1218 дней.     

Теперь рассмотрим чуть более сложный пример с подклассами и методами. Предположим, что нам нужно разработать CRM для автосалона. В ПО автосалона должен быть класс Vehicle (транспортное средство), который имеет набор атрибутов:

  • марка;
  • модель;
  • год выпуска;
  • стоимость.

Среди методов должна быть операция display_info(), которая отображает информацию о конкретном транспортном средстве, а помимо классов, в ПО необходимо использовать подклассы.

Подкласс – это класс, который наследует все атрибуты и методы родительского класса (также известного как базовый класс или суперкласс), но при этом может иметь дополнительные, свои собственные, атрибуты и методы. Концепцию наследования мы подробнее разберем ниже.

В ПО для автосалона необходимо создать подкласс Car (легковой автомобиль), который наследует все атрибуты и методы класса Vehicle, и при этом имеет дополнительные атрибуты, например количество дверей и стиль кузова. Аналогично, мы можем создать подкласс Truck (грузовик), который наследует все атрибуты и методы класса Vehicle, и к тому же имеет свои атрибуты – длину кузова и тяговую мощность.

В итоге, взаимодействие классов, подклассов и методов будет выглядеть так:

         class Vehicle:     def __init__(self, make, model, year, price):         self.make = make         self.model = model         self.year = year         self.price = price      def display_info(self):         print(f"Марка: {self.make}"         f"nМодель: {self.model}"         f"nГод выпуска: {self.year}"         f"nСтоимость: {self.price} руб")  class Car(Vehicle):     def __init__(self, make, model, year, price, num_doors, body_style):         super().__init__(make, model, year, price)         self.num_doors = num_doors         self.body_style = body_style  class Truck(Vehicle):     def __init__(self, make, model, year, price, bed_length, towing_capacity):         super().__init__(make, model, year, price)         self.bed_length = bed_length         self.towing_capacity = towing_capacity      

Создадим экземпляры классов и вызовем метод display_info() для вывода информации о них:

         # создаем объект "легковой автомобиль" car = Car("Toyota", "Camry", 2022, 2900000, 4, "седан")  # создаем объект "грузовик" truck = Truck("Ford", "F-MAX", 2023, 6000000, "6162", "13 т")  # выводим информацию о легковом автомобиле и грузовике car.display_info() truck.display_info()      

Результат:

         Марка: Toyota Модель: Camry Год выпуска: 2022 Стоимость: 2900000 руб Марка: Ford Модель: F-MAX Год выпуска: 2023 Стоимость: 6000000 руб      

В этом примере используется встроенная функция super(), которая позволяет вызывать методы родительского суперкласса из подкласса. Этот прием позволяет переиспользовать методы и расширять их функциональность. В данном случае вызывается метод инициализации super().__init__, который позволяет применить атрибуты суперкласса к подклассу. При необходимости, помимо унаследованных, можно определить новые свойства, которые относятся только к конкретному подклассу.

Рассмотрим еще один пример – библиотечную программу для хранения информации о книгах и их статусах (есть в наличии, выдана абоненту, получена от абонента и так далее). Здесь класс Book определяет различные характеристики книги – title, author, ISBN, а также задает методы check_out() и check_in(), которые выдают / принимают книги, и сообщают о статусах:

         class Book:     def __init__(self, title, author, isbn):         self.title = title         self.author = author         self.isbn = isbn         self.checked_out = False      def check_out(self):         if self.checked_out:             print("Книга находится у абонента.")         else:             self.checked_out = True             print("Выдаем книгу абоненту.")      def check_in(self):         if not self.checked_out:             print("Книга в наличии.")         else:             self.checked_out = False             print("Принимаем книгу в библиотеку.")      

Создадим объект книги и проверим статусы:

         # создаем объект книги book1 = Book("Война и мир", "Л.Н. Толстой", "978-0743273565")  # выдаем книгу, проверяем статус book1.check_out()  # проверяем статус повторно book1.check_out()  # принимаем книгу от читателя book1.check_in()  # проверяем статус книги повторно book1.check_in()      

Результат:

         Выдаем книгу абоненту. Книга находится у абонента. Принимаем книгу в библиотеку. Книга в наличии.      

Классы, объекты, атрибуты и методы – самые простые, самые базовые понятия ООП. Эти базовые концепции, в свою очередь, лежат в основе фундаментальных принципов ООП.

Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека питониста» Интересно, перейти к каналу

Фундаментальные принципы ООП

ООП основывается на четырех фундаментальных принципах: инкапсуляции, наследовании, полиморфизме и абстракции.

Инкапсуляция – механизм сокрытия деталей реализации класса от других объектов. Достигается путем использования модификаторов доступа public, private и protected, которые соответствуют публичным, приватным и защищенным атрибутам.

Наследование – процесс создания нового класса на основе существующего класса. Новый класс, называемый подклассом или производным классом, наследует свойства и методы существующего класса, называемого суперклассом или базовым классом.

Полиморфизм – способность объектов принимать различные формы. В ООП полиморфизм позволяет рассматривать объекты разных классов так, как если бы они были объектами одного класса.

Абстракция – процесс определения существенных характеристик объекта и игнорирования несущественных характеристик. Это позволяет создавать абстрактные классы, которые определяют общие свойства и поведение группы объектов, не уточняя детали каждого объекта.

В этой статье мы рассмотрим на конкретных примерах первые две концепции, а в следующей – остальные.

Инкапсуляция

Сделаем атрибуты title, author и isbn класса Book приватными – теперь доступ к ним возможен только внутри класса:

         class Book:     def __init__(self, title, author, isbn):         self.__title = title  # приватный         self.__author = author  # приватный         self.__isbn = isbn  # приватный      

Чтобы получить доступ к этим атрибутам извне класса, мы определяем методы getter и setter, которые обеспечивают контролируемый доступ к атрибутам:

             def get_title(self):         return self.__title      def set_title(self, title):         self.__title = title      def get_author(self):         return self.__author      def set_author(self, author):         self.__author = author      def get_isbn(self):         return self.__isbn      def set_isbn(self, isbn):         self.__isbn = isbn      

В этом примере методы get_title(), get_author() и get_isbn() являются получающими методами (геттерами), которые позволяют нам получать значения приватных атрибутов извне класса. Методы set_title(), set_author() и set_isbn() устанавливающие методы (сеттеры), которые позволяют нам устанавливать значения частных атрибутов извне класса.

Создадим экземпляр объекта и попытаемся получить доступ к его названию с помощью обычного метода:

         book1 = Book("Террор", "Дэн Симмонс", "558-0743553565")  # пытаемся получить доступ к приватному атрибуту print(book1.__title)      

Результат – ошибка:

         AttributeError: 'Book' object has no attribute '__title'      

Воспользуемся геттерами:

         # получаем приватные атрибуты с помощью геттеров print(book1.get_title()) print(book1.get_author()) print(book1.get_isbn())      

Результат:

         Террор Дэн Симмонс 558-0743553565      

Изменим название с помощью сеттера и выведем результат:

         # изменяем название с помощью сеттера book1.set_title("Эндимион") print(book1.get_title())      

Результат:

         Эндимион      

Наследование

Для иллюстрации концепции наследования мы определим класс Publication, который имеет свойства, общие для всех публикаций – title, author и year, а также общий метод display():

         class Publication:     def __init__(self, title, author, year):         self.title = title         self.author = author         self.year = year      def display(self):         print("Название:", self.title)         print("Автор:", self.author)         print("Год выпуска:", self.year)      

Теперь создадим два подкласса Book и Magazine, которые наследуют все свойства и методы от класса Publication, и кроме того, имеют свои атрибуты. Подкласс Book добавляет свойство isbn и переопределяет метод display() для включения свойства isbn. Подкласс Magazine добавляет свойство issue_number (номер выпуска) и переопределяет метод display() для включения свойства issue_number:

         class Book(Publication):     def __init__(self, title, author, year, isbn):         super().__init__(title, author, year)         self.isbn = isbn      def display(self):         super().display()         print("ISBN:", self.isbn)  class Magazine(Publication):     def __init__(self, title, author, year, issue_number):         super().__init__(title, author, year)         self.issue_number = issue_number      def display(self):         super().display()         print("Номер выпуска:", self.issue_number)      

Теперь, если мы создадим экземпляр класса Book или класса Magazine, мы сможем вызвать метод display() для отображения свойств объекта. Сначала будет вызван метод display() подкласса (Book или Magazine), который в свою очередь вызовет метод display() суперкласса Publication с помощью функции super(). Это позволяет нам повторно использовать код суперкласса и избежать дублирования кода в подклассах:

         # создаем объект книги book1 = Book("Выбор", "Эдит Эгер", 2019, "112-3333273566")  # создаем объект выпуска журнала magazine1 = Magazine("Вокруг света", "коллектив авторов", 2023, 3)  # выводим информацию о книге и номере журнала book1.display() magazine1.display()      

Результат:

         Название: Выбор Автор: Эдит Эгер Год выпуска: 2019 ISBN: 112-3333273566 Название: Вокруг света Автор: коллектив авторов Год выпуска: 2023 Номер выпуска: 3      

Практика

Задание 1

Напишите класс MusicAlbum, у которого есть:

  • Атрибуты title, artist, release_year, genre, tracklist (название, исполнитель, год выхода, жанр, список треков.
  • Метод play_random_track() для вывода случайного названия песни.

Пример использования:

         album4 = MusicAlbum("Deutschland", "Rammstein", 2019, "Neue Deutsche Härte",                      ["Deutschland", "Radio", "Zeig dich", "Ausländer", "Sex",                       "Puppe", "Was ich liebe", "Diamant", "Weit weg", "Tattoo",                       "Hallomann"]) print("Название:", album4.title) print("Исполнитель:", album4.artist) print("Год:", album4.release_year) print("Жанр:", album4.genre) print("Треки:", album4.tracklist) album4.play_random_track()      

Вывод:

         Название: Deutschland Исполнитель: Rammstein Год: 2019 Жанр: Neue Deutsche Härte Треки: ['Deutschland', 'Radio', 'Zeig dich', 'Ausländer', 'Sex', 'Puppe', 'Was ich liebe', 'Diamant', 'Weit weg', 'Tattoo', 'Hallomann'] Воспроизводится трек 7: Was ich liebe      

Решение:

         import random  class MusicAlbum:     def __init__(self, title, artist, release_year, genre, tracklist):         self.title = title         self.artist = artist         self.release_year = release_year         self.genre = genre         self.tracklist = tracklist          def play_track(self, track_number):         print(f"Воспроизводится трек  {track_number}: {self.tracklist[track_number - 1]}")          def play_random_track(self):         track_number = random.randint(1, len(self.tracklist))         self.play_track(track_number)     

Задание 2

Создайте класс Student, который имеет:

  • атрибуты name, age, grade, scores (имя, возраст, класс, оценки);
  • метод average_score – для вычисления среднего балла успеваемости.

Пример использования:

         student2 = Student("Егор Данилов", 12, "5B", [5, 4, 4, 5]) print("Имя:", student2.name) print("Возраст:", student2.age) print("Класс:", student2.grade) print("Оценки:", *student2.scores) print("Средний балл:", student2.average_score())      

Вывод:

         Имя: Егор Данилов Возраст: 12 Класс: 5B Оценки: 5 4 4 5 Средний балл: 4.5      

Решение:

         class Student:     def __init__(self, name, age, grade, scores):         self.name = name         self.age = age         self.grade = grade         self.scores = scores          def average_score(self):         return sum(self.scores) / len(self.scores)      

Задание 3

Напишите класс Recipe с двумя методами:

  • print_ingredients(self) – выводит список продуктов, необходимых для приготовления блюда;
  • cook(self) – сообщает название выбранного рецепта и уведомляет о готовности блюда.

Пример использования:

         # создаем рецепт спагетти болоньезе spaghetti = Recipe("Спагетти болоньезе", ["Спагетти", "Фарш", "Томатный соус", "Лук", "Чеснок", "Соль"])  # печатаем список продуктов для рецепта спагетти spaghetti.print_ingredients()  # готовим спагетти spaghetti.cook()    # создаем рецепт для кекса cake = Recipe("Кекс", ["Мука", "Яйца", "Молоко", "Сахар", "Сливочное масло", "Соль", "Ванилин"])  # печатаем рецепт кекса cake.print_ingredients()  # готовим кекс cake.cook()       

Вывод:

         Ингредиенты для Спагетти болоньезе: - Спагетти - Фарш - Томатный соус - Лук - Чеснок - Соль Сегодня мы готовим Спагетти болоньезе. Выполняем инструкцию по приготовлению блюда Спагетти болоньезе... Блюдо Спагетти болоньезе готово! Ингредиенты для Кекс: - Мука - Яйца - Молоко - Сахар - Сливочное масло - Соль - Ванилин Сегодня мы готовим Кекс. Выполняем инструкцию по приготовлению блюда Кекс... Блюдо Кекс готово!     

Решение:

         class Recipe:     def __init__(self, name, ingredients):         self.name = name         self.ingredients = ingredients      def print_ingredients(self):         print(f"Ингредиенты для {self.name}:")         for ingredient in self.ingredients:             print(f"- {ingredient}")          def cook(self):         print(f"Сегодня мы готовим {self.name}.")         print(f"Выполняем инструкцию по приготовлению блюда {self.name}...")         print(f"Блюдо {self.name} готово!")               

Задание 4

Напишите суперкласс Publisher (издательство) и два подкласса BookPublisher (книжное издательство) и NewspaperPublisher (газетное издательство).

Родительский класс Publisher имеет два атрибута name и location (название, расположение) и два метода:

  • get_info(self) – предоставляет информацию о названии и расположении издательства;
  • publish(self, message) – выводит информацию об издании, которое находится в печати.

Подклассы BookPublisher и NewspaperPublisher используют метод super().__init__(name, location) суперкласса для вывода информации о своих названии и расположении, и кроме того, имеют собственные атрибуты:

  • BookPublisher – num_authors (количество авторов).
  • NewspaperPublisher– num_pages (количество страниц в газете).

Пример использования:

         publisher = Publisher("АБВГД Пресс", "Москва") publisher.publish("Справочник писателя")  book_publisher = BookPublisher("Важные Книги", "Самара", 52) book_publisher.publish("Приключения Чебурашки", "В.И. Пупкин")  newspaper_publisher = NewspaperPublisher("Московские вести", "Москва", 12) newspaper_publisher.publish("Новая версия Midjourney будет платной")      

Вывод:

         Готовим "Справочник писателя" к публикации в АБВГД Пресс (Москва) Передаем рукопись 'Приключения Чебурашки', написанную автором В.И. Пупкин в издательство Важные Книги (Самара) Печатаем свежий номер со статьей "Новая версия Midjourney будет платной" на главной странице в издательстве Московские вести (Москва)      

Решение:

         class Publisher:     def __init__(self, name, location):         self.name = name         self.location = location          def get_info(self):         return f"{self.name} ({self.location})"          def publish(self, message):         print(f'Готовим "{message}" к публикации в {self.get_info()}')      class BookPublisher(Publisher):     def __init__(self, name, location, num_authors):         super().__init__(name, location)         self.num_authors = num_authors          def publish(self, title, author):         print(f"Передаем рукопись '{title}', написанную автором {author} в издательство {self.get_info()}")      class NewspaperPublisher(Publisher):     def __init__(self, name, location, num_pages):         super().__init__(name, location)         self.num_pages = num_pages          def publish(self, headline):         print(f'Печатаем свежий номер со статьей "{headline}" на главной странице в издательстве {self.get_info()}')      

Задание 5

Создайте класс BankAccount, который имеет следующие свойства:

  • balance – приватный атрибут для хранения текущего баланса счета;
  • interest_rate –приватный атрибут для процентной ставки;
  • transactions – приватный атрибут для списка всех операций, совершенных по счету.

Класс BankAccount должен иметь следующие методы:

  • deposit(amount) – добавляет сумму к балансу и регистрирует транзакцию;
  • withdraw(amount) – вычитает сумму из баланса и записывает транзакцию;
  • add_interest() – добавляет проценты к счету на основе interest_rate и записывает транзакцию;
  • history() – печатает список всех операций по счету.

Пример использования:

         # создаем объект счета с балансом 100000 и процентом по вкладу 0.05 account = BankAccount(100000, 0.05)  # вносим 15 тысяч на счет account.deposit(15000)  # снимаем 7500 рублей account.withdraw(7500)  # начисляем проценты по вкладу account.add_interest()  # печатаем историю операций account.history()      

Вывод:

         Внесение наличных на счет: 15000 Снятие наличных: 7500 Начислены проценты по вкладу: 5375.0       

Решение:

         class BankAccount:     def __init__(self, balance, interest_rate):         self.__balance = balance         self.__interest_rate = interest_rate         self.__transactions = []      def deposit(self, amount):         self.__balance += amount         self.__transactions.append(f"Внесение наличных на счет: {amount}")      def withdraw(self, amount):         if self.__balance >= amount:             self.__balance -= amount             self.__transactions.append(f"Снятие наличных: {amount}")         else:             print("Недостаточно средств на счете")      def add_interest(self):         interest = self.__balance * self.__interest_rate         self.__balance += interest         self.__transactions.append(f"Начислены проценты по вкладу: {interest}")      def history(self):         for transaction in self.__transactions:             print(transaction)      

Задание 6

Создайте класс Employee (сотрудник), который имеет следующие приватные свойства:

  • name – имя сотрудника;
  • age – возраст;
  • salary – оклад;
  • bonus – премия.

Класс Employee должен иметь следующие методы:

  • get_name() – возвращает имя сотрудника;
  • get_age() – возвращает возраст;
  • get_salary() – возвращает зарплату сотрудника;
  • set_bonus(bonus) – устанавливает свойство bonus;
  • get_bonus() – возвращает бонус для сотрудника;
  • get_total_salary() – возвращает общую зарплату сотрудника (оклад + бонус).

Пример использования:

         # создаем сотрудника с именем, возрастом и зарплатой employee = Employee("Марина Арефьева", 30, 90000)  # устанавливаем бонус для сотрудника employee.set_bonus(15000)  # выводим имя, возраст, зарплату, бонус и общую зарплату сотрудника print("Имя:", employee.get_name()) print("Возраст:", employee.get_age()) print("Зарплата:", employee.get_salary()) print("Бонус:", employee.get_bonus()) print("Итого начислено:", employee.get_total_salary())      

Вывод:

         Имя: Марина Арефьева Возраст: 30 Зарплата: 90000 Бонус: 15000 Итого начислено: 105000      

Решение:

         class Employee:     def __init__(self, name, age, salary):         self.__name = name         self.__age = age         self.__salary = salary         self.__bonus = 0      def get_name(self):         return self.__name      def get_age(self):         return self.__age      def get_salary(self):         return self.__salary      def set_bonus(self, bonus):         self.__bonus = bonus      def get_bonus(self):         return self.__bonus      def get_total_salary(self):         return self.__salary + self.__bonus      

Задание 7

Напишите класс Animal, обладающий свойствами name, species, legs, в которых хранятся данные о кличке, виде и количестве ног животного. Класс также должен иметь два метода – voice() и move(), которые сообщают о том, что животное подает голос и двигается.

Создайте два подкласса – Dog и Bird. Подкласс Dog имеет атрибут breed (порода) и метод bark(), который сообщает о том, что собака лает. Подкласс Bird обладает свойством wingspan (размах крыльев) и методом fly(), который уведомляет о полете птицы.

Пример использования:

         dog = Dog("Геральт", "доберман", 4) bird = Bird("Вася", "попугай", 2) dog.voice() bird.voice() dog.move() bird.move() dog.bark() bird.fly()      

Вывод:

         Геральт подает голос Вася подает голос Геральт дергает хвостом Вася дергает хвостом доберман Геральт лает попугай Вася летaeт      

Решение:

         class Animal:     def __init__(self, name, species, legs):         self.name = name         self.species = species         self.legs = legs      def voice(self):         print(f"{self.name} подает голос")      def move(self):         print(f"{self.name} дергает хвостом")  class Dog(Animal):     def __init__(self, name, breed, legs):         super().__init__(name, breed, legs)         self.breed = breed      def bark(self):         print(f"{self.breed} {self.name} лает")  class Bird(Animal):     def __init__(self, name, species, wingspan):         super().__init__(name, species, 2)         self.wingspan = wingspan      def fly(self):         print(f"{self.species} {self.name} летaeт")      

Задание 8

Создайте класс Shape (геометрическая фигура) со свойствами name и color (название и цвет). У этого класса должны быть три подкласса – Circle (окружность), Rectangle (прямоугольник), и Triangle (треугольник). Каждый подкласс наследует атрибут color и метод describe() родительского класса Shape, и при этом имеет дополнительные свойства и методы:

  • Circle – атрибут radius и метод area() для вычисления площади.
  • Rectangle – атрибуты length и width, свой метод area().
  • Triangle – атрибуты base и height (основание и высота), собственный метод area().

Пример использования:

         circle = Circle("красный", 5) rectangle = Rectangle("синий", 3, 4) triangle = Triangle("фиолетовый", 6, 8) circle.describe() rectangle.describe()  triangle.describe() print(f"Площадь треугольника {triangle.area()}, окружности {circle.area()}, прямоугольника {rectangle.area()} см.")      

Вывод:

         Это геометрическая фигура, цвет - красный. Это окружность. Радиус - 5 см, цвет - красный. Это геометрическая фигура, цвет - синий. Это синий прямоугольник. Длина - 3 см, ширина - 4 см. Это геометрическая фигура, цвет - фиолетовый. Это фиолетовый треугольник с основанием 6 см и высотой 8 см. Площадь треугольника 24.0, окружности 78.5, прямоугольника 12 см.      

Решение:

         class Shape:     def __init__(self, color):         self.color = color          def describe(self):         print(f"Это геометрическая фигура, цвет - {self.color}.")           class Circle(Shape):     def __init__(self, color, radius):         super().__init__(color)         self.radius = radius          def area(self):         return 3.14 * self.radius ** 2          def describe(self):         super().describe()         print(f"Это окружность. Радиус - {self.radius} см, цвет - {self.color}.")           class Rectangle(Shape):     def __init__(self, color, length, width):         super().__init__(color)         self.length = length         self.width = width          def area(self):         return self.length * self.width          def describe(self):         super().describe()         print(f"Это {self.color} прямоугольник. Длина - {self.length} см, ширина - {self.width} см.")           class Triangle(Shape):     def __init__(self, color, base, height):         super().__init__(color)         self.base = base         self.height = height          def area(self):         return 0.5 * self.base * self.height          def describe(self):         super().describe()         print(f"Это {self.color} треугольник с основанием {self.base} см и высотой {self.height} см.")      

Задание 9

Для ПО кондитерской фабрики нужно написать родительский класс Candy (Конфеты). Этот класс имеет атрибуты name, price, weight (наименование, цена, вес). Подклассы Chocolate, Gummy, HardCandy (шоколад, жевательный мармелад, леденец) наследуют все атрибуты суперкласса Candy. Кроме того, у них есть и свои атрибуты:

  • Chocolatecocoa_percentage (процент содержания какао) и chocolate_type (сорт шоколада).
  • Gummyflavor и shape (вкус и форма).
  • HardCandyflavor и filled (вкус и начинка).

Пример использования:

         chocolate = Chocolate(name="Швейцарские луга", price=325.50, weight=220, cocoa_percentage=40, chocolate_type="молочный") gummy = Gummy(name="Жуй-жуй", price=76.50, weight=50, flavor="вишня", shape="медведь") hard_candy = HardCandy(name="Crazy Фрукт", price=35.50, weight=25, flavor="манго", filled=True)  print("Шоколадные конфеты:") print(f"Название конфет: {chocolate.name}") print(f"Стоимость: {chocolate.price} руб") print(f"Вес брутто: {chocolate.weight} г") print(f"Процент содержания какао: {chocolate.cocoa_percentage}") print(f"Тип шоколада: {chocolate.chocolate_type}") print("nМармелад жевательный:") print(f"Название конфет: {gummy.name}") print(f"Стоимость: {gummy.price} руб") print(f"Вес брутто: {gummy.weight} г") print(f"Вкус: {gummy.flavor}") print(f"Форма: {gummy.shape}") print("nФруктовые леденцы:") print(f"Название конфет: {hard_candy.name}") print(f"Стоимость: {hard_candy.price} руб") print(f"Вес брутто: {hard_candy.weight} г") print(f"Вкус: {hard_candy.flavor}") print(f"Начинка: {hard_candy.filled}")      

Вывод:

         Шоколадные конфеты: Название конфет: Швейцарские луга Стоимость: 325.5 руб Вес брутто: 220 г Процент содержания какао: 40 Тип шоколада: молочный  Мармелад жевательный: Название конфет: Жуй-жуй Стоимость: 76.5 руб Вес брутто: 50 г Вкус: вишня Форма: медведь  Фруктовые леденцы: Название конфет: Crazy Фрукт Стоимость: 35.5 руб Вес брутто: 25 г Вкус: манго Начинка: True      

Решение:

         class Candy:     def __init__(self, name, price, weight):         self.name = name         self.price = price         self.weight = weight  class Chocolate(Candy):     def __init__(self, name, price, weight, cocoa_percentage, chocolate_type):         super().__init__(name, price, weight)         self.cocoa_percentage = cocoa_percentage         self.chocolate_type = chocolate_type  class Gummy(Candy):     def __init__(self, name, price, weight, flavor, shape):         super().__init__(name, price, weight)         self.flavor = flavor         self.shape = shape  class HardCandy(Candy):     def __init__(self, name, price, weight, flavor, filled):         super().__init__(name, price, weight)         self.flavor = flavor         self.filled = filled      

Задание 10

Для военной игры-стратегии нужно написать класс Soldier (солдат). Класс имеет атрибуты name, rank и service_number (имя, воинское звание, порядковый номер), причем звание и номер – приватные свойства.

Напишите методы для:

  • получения воинского звания;
  • подтверждения порядкового номера;
  • повышения в звании;
  • понижения в звании.

Кроме того, нужно создать декоратор для вывода информации о персонаже.

Пример использования:

         soldier1 = Soldier("Иван Сусанин", "рядовой", "12345") soldier1.get_rank()   soldier1.promote()    soldier1.demote()         

Вывод:

         Создан новый игровой персонаж типа Soldier с атрибутами: {'name': 'Иван Сусанин', '_Soldier__rank': 'рядовой', '_Soldier__service_number': '12345'} Персонаж Иван Сусанин имеет звание рядовой Иван Сусанин повышен в звании, он теперь ефрейтор Иван Сусанин понижен в звании, он теперь рядовой      

Решение:

         RANKS = ["рядовой", "ефрейтор", "младший сержант", "сержант", "старший сержант",          "прапорщик", "старший прапорщик"]  def print_info(cls):     class NewClass(cls):         def __init__(self, *args, **kwargs):             super().__init__(*args, **kwargs)             print(f"Создан новый игровой персонаж типа {cls.__name__} с атрибутами: {self.__dict__}")          def get_rank(self):             print(f"Персонаж {self.name} имеет звание {self._Soldier__rank}")          def promote(self):             super().promote()             print(f"{self.name} повышен в звании, он теперь {self._Soldier__rank}")          def demote(self):             super().demote()             print(f"{self.name} понижен в звании, он теперь {self._Soldier__rank}")      return NewClass  @print_info class Soldier:     def __init__(self, name, rank, service_number):         self.name = name         self.__rank = rank         self.__service_number = service_number      def verify_service_number(self, service_number):         return self.__service_number == service_number      def promote(self):         if self.__rank in RANKS[:-1]:             self.__rank = RANKS[RANKS.index(self.__rank) + 1]      def demote(self):         if self.__rank in RANKS[1:]:             self.__rank = RANKS[RANKS.index(self.__rank) - 1]      

Подведем итоги

Мы рассмотрели базовые понятия ООП – классы, объекты, методы, и научились решать задачи, связанные с инкапсуляцией и наследованием. В следующей статье будем изучать остальные фундаментальные принципы ООП – полиморфизм и абстракцию.

***

Содержание самоучителя

  1. Особенности, сферы применения, установка, онлайн IDE
  2. Все, что нужно для изучения Python с нуля – книги, сайты, каналы и курсы
  3. Типы данных: преобразование и базовые операции
  4. Методы работы со строками
  5. Методы работы со списками и списковыми включениями
  6. Методы работы со словарями и генераторами словарей
  7. Методы работы с кортежами
  8. Методы работы со множествами
  9. Особенности цикла for
  10. Условный цикл while
  11. Функции с позиционными и именованными аргументами
  12. Анонимные функции
  13. Рекурсивные функции
  14. Функции высшего порядка, замыкания и декораторы
  15. Методы работы с файлами и файловой системой
  16. Регулярные выражения
  17. Основы скрапинга и парсинга
  18. Основы ООП: инкапсуляция и наследование

  • 0 views
  • 0 Comment

Leave a Reply

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Связаться со мной
Close