Простой Python. Современный стиль программирования (Любанович) - страница 88

>…·····def need_a_push(self):

>…·········print("A little help here?")

>…

Далее создадим объекты классов Car и Yugo:

>>>> give_me_a_car = Car()

>>>> give_me_a_yugo = Yugo()

Объект класса Yugo может реагировать на вызов метода need_a_push():

>>>> give_me_a_yugo.need_a_push()

>A little help here?

А объект общего класса Car — нет:

>>>> give_me_a_car.need_a_push()

>Traceback (most recent call last):

>··File "", line 1, in

>AttributeError: 'Car' object has no attribute 'need_a_push'

К этому моменту класс Yugo может делать что-то, чего не может делать класс Car, и теперь мы точно можем определить отдельную личность класса Yugo.

Просим помощи у предка с помощью ключевого слова super

Мы видели, как класс-потомок может добавить или перегрузить метод класса-предка. Но что, если вам нужно вызвать оригинальный метод родительского класса? «Рад, что вы спросили», — говорит метод super(). Мы определим новый класс, который называется EmailPerson и представляет объект класса Person, содержащий адрес электронной почты. Для начала запишем наше привычное определение класса Person:

>>>> class Person():

>…·····def __init__(self, name):

>…·········self.name = name

>…

Обратите внимание на то, что вызов метода __init__() в следующем подклассе имеет дополнительный параметр email:

>>>> class EmailPerson(Person):

>…·····def __init__(self, name, email):

>…·········super().__init__(name)

>…·········self.email = email

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

• Метод super() получает определение родительского класса Person.

• Метод __init__() вызывает метод Person.__init__(). Последний заботится о том, чтобы передать аргумент self суперклассу, поэтому вам нужно лишь передать опциональные аргументы. В нашем случае единственным аргументом класса Person() будет name.

• Строка self.email = email — это новый код, который отличает класс EmailPerson от класса Person.

Теперь создадим одну персону:

>>>> bob = EmailPerson('Bob Frapples', 'bob@frapples.com')

Мы должны иметь доступ к атрибутам name и email:

>>>> bob.name

>'Bob Frapples'

>>>> bob.email

>'bob@frapples.com'

Почему бы нам просто не определить новый класс так, как показано далее?

>>>> class EmailPerson(Person):

>…·····def __init__(self, name, email):

>…·········self.name = name

>…·········self.email = email

Мы могли бы сделать это, но в таком случае потеряли бы возможность применять наследование. Мы использовали метод super(), чтобы создать объект, который работает примерно так же, как и объект класса Person. Есть и другое преимущество: если определение класса Person в будущем изменится, с помощью метода super() мы сможем гарантировать, что атрибуты и методы, которые класс EmailPerson наследует от класса Person, отреагируют на изменения.