← Часть 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 . Кроме того, у них есть и свои атрибуты:
Chocolate – cocoa_percentage (процент содержания какао) и chocolate_type (сорт шоколада).
Gummy – flavor и shape (вкус и форма).
HardCandy – flavor и 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]
Подведем итоги
Мы рассмотрели базовые понятия ООП – классы, объекты, методы, и научились решать задачи, связанные с инкапсуляцией и наследованием. В следующей статье будем изучать остальные фундаментальные принципы ООП – полиморфизм и абстракцию.
***
Содержание самоучителя
Особенности, сферы применения, установка, онлайн IDE
Все, что нужно для изучения Python с нуля – книги, сайты, каналы и курсы
Типы данных: преобразование и базовые операции
Методы работы со строками
Методы работы со списками и списковыми включениями
Методы работы со словарями и генераторами словарей
Методы работы с кортежами
Методы работы со множествами
Особенности цикла for
Условный цикл while
Функции с позиционными и именованными аргументами
Анонимные функции
Рекурсивные функции
Функции высшего порядка, замыкания и декораторы
Методы работы с файлами и файловой системой
Регулярные выражения
Основы скрапинга и парсинга
Основы ООП: инкапсуляция и наследование