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

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

< Лекция 1 || Лекция 23: 1234

Смотреть на youtube

Класс Rational является хорошим примером создания в Pythonодного класса. Давайте рассмотрим, как в языке реализуется создание семейства классов, связанных отношениями наследования.

Наследование. Конструкторы и метод str

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

Посмотрим, как эта концепция реализуется в Python. Создадим в нашем Решении новый проект с именем Inheritance. Соответственно в проекте появится модуль с этим именем. Добавим в проект два класса - Father и Son, связанных отношением наследования. Каждый класс будем записывать в отдельный модуль класса. Так что в проекте Inheritance появятся дополнительно два модуля Father и Son.

Содержательная сторона классов нас особо не интересует. У класса Father зададим три поля и два метода - конструктор и метод __str__, позволяющий выводить на печать информацию об объекте. Вот описание этого класса:

class Father(object):    
    """SimpleTest of Inheritance
       Father and Son
    """
    #Fields of class Father
    #first_name: string
    #last_name: string
    #town : string
    def __init__(self, first_name, last_name, town):
        self.first_name = first_name
        self.last_name = last_name
        self.town = town
    def __str__(self):
        return ('fam = ' + self.last_name + ' ' + self.first_name  +
               ' town = ' + self.town)

В сравнении с ранее построенным классом Rational в этом описании ничего нового нет.

Построим теперь класс Son - потомок класса Father. Наш потомок ничего не создает, наследуя все от своего родителя. Заметьте, что в Python конструктор может наследоваться и его можно не задавать, если потомок не добавляет новых полей:

from Father import Father
class Son(Father):
    """
    sub class of super class Father
    """ 

Заметьте, поскольку классы находятся в отдельных модулях, то определению класса Son должен предшествовать импорт родительского класса.

В нашем примере класс Son ничего не определяет, ничего не создает, все наследует от родителя - и конструктор и метод str.

Модуль Inheritance в нашем проекте будет играть роль модуля тестера, так что все тесты будем помещать в этот модуль. Приведу тест, в котором создаются объекты как родительского класса, так и класса потомка:

"""
tester class 
"""
from Father import Father
from Son import Son
def test1():
    """
    Create objects Father and Son
    """
    f1 = Father('Vladimir', 'Petrov', 'Tver')
    print('Father: ', f1)
    s1 = Son('Ilya', 'Petrov', 'Moscow')
    print('Son: ', s1)

Вот результаты работы этого теста


Потомок, который ничего не делает не интересен. Поэтому будем усложнять ситуацию. Начнем с того, что добавим в класс Son новое свойство - возраст объекта - атрибут age. Как следствие, у потомка появится конструктор и изменится метод str. Вот описание конструктора класса:

def __init__(self, first_name, last_name, town, age):
        super().__init__(first_name, last_name, town)
 self.age = age

Конструктор потомка вызывает конструктор родителя, передает ему необходимые параметры, а затем выполняет свою часть работы. Для обращения к атрибутам родительского класса, в частности, вызова его методов используется конструкция super().

Аналогично, модифицированный метод __str__ вызывает родительский метод, присоединяя к результату его работы свою часть информации:

def __str__(self):
    return super().__str__() + ' age = ' + str(self.age) 

В следующем тесте создадим новый объект класса Son, у которого уже будет дополнительный атрибут:

def test2():
    s = Son('Mike', 'Petrov', 'Praga', 27 )
    print('Son: ', s)

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


Давайте добавим в проект еще один класс - Daughter - потомка класса Son. В этом классе добавим новый атрибут и соответственно переопределим конструктор и метод __str__:

from Son import Son
class Daughter(Son):
    """
    Потомок класса Father 
    Прямой потомок класса Son
    """
    def __init__(self, first_name, last_name, town, age, sex):
        super().__init__(first_name, last_name, town, age)
        self.sex = sex

    def __str__(self):
        return super().__str__() + ' sex = ' + self.sex

Никакие новые особенности при расширении дерева наследования не возникают. Создадим объекты, определенные на разных уровнях иерархии наследования:

def test3():
    f = Father('Vladimir', 'Petrov', 'Tver')
    s1 = Son('Ilya', 'Petrov', 'Moscow', 31)
    s2 = Son('Mike', 'Petrov', 'Praga', 27 )
    gd = Daughter('Anna', 'Petrova', 'Moscow', 4, 'f')
    print('Father: ', f)
    print('Son: ', s1)
    print('Son: ', s2)
    print('Daughter: ', gd)

Вот результат работы этого теста:


< Лекция 1 || Лекция 23: 1234
Елена Лаптева
Елена Лаптева

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

Михаил Сидоров
Михаил Сидоров

Если S - последовательность, то срез задается как S(i : j) и содержит j - i элементов,

а в примере используютс другие скобки - 

NL[1:3] = ["решили", "не", "искать"]

или это не срез, тогда, что это?