НОЧУ ДПО "Национальный открытый университет "ИНТУИТ"
Опубликован: 24.01.2021 | Доступ: свободный | Студентов: 2489 / 106 | Длительность: 03:57:00
Лекция 25:

Наследование и вложенность

< Лекция 1 || Лекция 25: 123

Особенности классов Python

Смотреть на youtube

До сих пор я старался показать, что на Python можно работать с классами в стиле, привычном для работы с классами в таких языках как, например, C# или Java. В этой модели класс является декларацией - описанием некоторого множества объектов. Это описание включает описание свойств объектов и их поведения. Свойства объектов задаются полями класса, поведение - методами. Каждый класс имеет конструктор объектов. Если конструктор явно не задан, то в класс добавляется конструктор по умолчанию. Создать объект можно только вызвав конструктор. Все объекты класса в момент создания получают один и тот же набор свойств, значения свойств могут отличаться. Изменить описание класса и заданный набор свойств динамически невозможно.

Эта модель обычно расширяется, поскольку кроме полей, принадлежащих объектам, в классе могут быть заданы поля, принадлежащие классу, существующие в единственном экземпляре и доступные всем объектам - экземплярам класса. В языке C# такие поля объявляются как статические. У класса могут быть и статические методы, работающие только со статическими полями. Сам класс может быть объявлен как статический. Тогда он является модулем, существует в единственном экземпляре, его методы являются сервисами, которые такой класс предоставляет другим классам.

Модель класса Pythonсущественно богаче. Вот основные отличия:

  • Класс - это объект, а не декларация.
  • Класс - это динамически создаваемый объект, который может модифицироваться в ходе выполнения.
  • Объекты класса могут иметь не только разные значения свойств, но и наборы их свойств могут отличаться.
  • Метакласс - это класс, объектами которого являются классы.

Остановимся более подробно на рассмотрении атрибутов класса, задающих свойства класса и его объектов. В Pythonатрибуты могут быть четырех типов:

  • Атрибуты, принадлежащие классу. Они существуют в единственном экземпляре, не входят в состав атрибутов объекта, но доступны объектам как для чтения, так и для записи. Они могут играть роль счетчиков, фиксируя, например, число объектов, создаваемых конструктором класса, или играть роль доски объявлений, что будет продемонстрировано в нижеследующем примере. Эти атрибуты являются аналогом static полей для классов C#. Атрибуты этого типа могут быть заданы и инициализированы на этапе описания класса.
  • Атрибуты, принадлежащие всем объектам класса. Эти атрибуты создаются конструктором класса. Конструктор, если он задается для класса, имеет фиксированное имя __init__. В конструкторе можно задать произвольное число аргументов, которые становятся атрибутами, входящими в состав любого создаваемого объекта класса. В момент создания объекта вызывается конструктор класса, которому нужно передать значения атрибутов. При объявлении конструктора можно задать значения атрибутов по умолчанию. Если конструктор определен, то задание атрибутов, определяемых конструктором, обязательно. Однако Pythonне требует обязательного включения конструктора в описание класса, так что общих атрибутов у объектов может и не быть.
  • Атрибуты, принадлежащие объекту по его желанию. В классе, помимо конструктора могут быть определены set методы, устанавливающие атрибуты. Эти атрибуты включаются в состав объекта динамически в тот момент, когда объект вызывает соответствующий set метод.
  • Индивидуальные атрибуты, не определяемые описанием класса. Эти атрибуты создаются динамически объектом, характеризуя его индивидуальность.

О методах класса Pythonуже многое было сказано, в частности об особенности реализации полиморфизма. Сейчас на примере класса Person и его объектов рассмотрим задание атрибутов всех четырех типов. Вот описание класса Person:

from CreatingStr import CreatingStr
class Person(CreatingStr):
    """
    Класс с динамически создаваемыми атрибутами 4-х типов:
    Атрибут messageBoard - один для всех экземпляров. 
    Он может создаваться в момент объявления класса,    
    либо класс может создавать его динамически. 
    В данном контексте играет роль доски объявлений (аналог static поля C#)
    Атрибуты fam и age создаются конструктором класса.
    Эти атрибуты всегда присутствуют в каждом экземпляре класса
    и должны быть заданы при создании экземпляра.
    Атрибут hobby, создается методом класса setHobby.
    Атрибут появляется у экземпляра, если он вызывает метод setHobby.
    Не все объекты класса обязаны иметь это свойство.
    Индивидуальный атрибут, такой как, например, loveBook
    создается экземпляром класса.
    """
    messageBoard = "Это доска объявлений. Пишите!"
    def __init__(self, fam, age):
        self.fam = fam
        self.age = age
    def setHobby(self, hobby):
        self.hobby = hobby
    def writeMessage(self, mes, new = "new"):
        if new == "new":
            Person.messageBoard = mes
        else:
            #new = "добавляем сообщение на доску"
            Person.messageBoard = Person.messageBoard + "\r\n " + mes
    

Класс Person является наследником инструментального класса CreatingStr, наследуемый метод str которого позволяет выдавать информацию об атрибутах, связанных с объектами класса.

Атрибут messageBoard, заданный на уровне класса, является атрибутом класса. Он не задает свойство, значения которого индивидуальны для каждого из объектов класса. Значение этого свойства доступны всем объектам как для чтения, так и для записи. В данном примере это свойство играет роль доски объявлений.

Конструктор класса init задает два атрибута - fam и age, обязательных для всех объектов.

Метод setHobby позволяет задавать объектам возможный, но не обязательный атрибут Hobby.

Объект класса может иметь и индивидуальный атрибут, не предусмотренный классом.

В класс включен метод writeMessage, позволяющий записывать или дописывать сообщения объектов в доску объявлений - атрибут messageBoard.

Давайте создадим несколько объектов класса Person, у которых наборы атрибутов будут отличаться:

from Person import Person
def test8():
    петр = Person("Петр Петров", 18)
    анна = Person("Анна Ананьева", 19)
    иван = Person("Иван Иванов", 20)
    анна.loveBook = "Мастер и Маргарита"
    петр.setHobby("Хоккей")
    company = [анна, иван, петр]
    for pers in company:
        print(pers)
    print("message: ", Person.messageBoard)
    анна.writeMessage("Анна: Приглашаю на встречу 23.01 в 15.00.")
    петр.writeMessage("Петр: Приду!", "add")
    иван.writeMessage("Иван: Буду!", "add")
    print("message: ", Person.messageBoard)

При создании объектов: петр, анна, иван вызывается конструктор класса, позволяющий задать индивидуальные значения обязательных свойств объектов - fam и age.

Объект петр динамически задает предусмотренное классом свойство, вызывая метод setHobby:

петр.setHobby("Хоккей")

Объект anna динамически создает индивидуальный атрибут, выполняя вызов:

анна.loveBook = "Мастер и Маргарита"

В тесте идет работа объектов с общим для всех атрибутом messageBoard. Для этого объекты используют метод writeMessage, позволяющий записывать или дописывать свои сообщения в доску объявлений messageBoard.

Давайте выполним этот тест.

Вот результаты:


Как видите, все три объекта имеют атрибуты age и fam, но состав атрибутов отличается. Объект "анна" создал индивидуальный атрибут, а "петр" - указал хобби. Используя общий атрибут, объекты смогли обменяться сообщениями.

< Лекция 1 || Лекция 25: 123
Алексей Авилов
Алексей Авилов

Неужели не нашлось русских специалистов, чтобы записать курс по пайтону ? Да, можно включить переводчик и слушать с переводом, но это что? Это кто-то считает хорошим и понятным курсом для начинающих? 

Елена Лаптева
Елена Лаптева

Думаю. что не смогу его закончить. Хотелось предупредить других - не тратьте зря время, ищите другой курс.