Неужели не нашлось русских специалистов, чтобы записать курс по пайтону ? Да, можно включить переводчик и слушать с переводом, но это что? Это кто-то считает хорошим и понятным курсом для начинающих? |
Наследование
Смотреть на 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)
Вот результат работы этого теста: