170
Глава 9 • Классы
Добавьте метод с именем increment_number_served(), который
увеличивает количество
обслуженных посетителей на заданную величину . Вызовите этот метод с любым числом,
которое могло бы представлять количество обслуженных клиентов — скажем, за один день .
9-5 . Попытки входа: добавьте атрибут login_attempts в класс User из упражнения 9-3
(с . 165) . Напишите метод increment_login_attempts(), увеличивающий значение login_
attempts на 1 . Напишите другой метод с именем reset_login_attempts(), обнуляющий значе-
ние login_attempts .
Создайте экземпляр класса User и вызовите increment_login_attempts() несколько раз . Вы-
ведите значение login_attempts, чтобы убедиться в том, что значение было изменено пра-
вильно, а затем вызовите reset_login_attempts() . Снова выведите login_attempts и убеди-
тесь в том, что значение обнулилось .
Наследование
Работа над новым классом не обязана начинаться с нуля. Если класс, который вы
пишете, представляет собой специализированную версию ранее написанного клас-
са, вы можете воспользоваться
наследованием
. Один класс,
наследующий
от другого,
автоматически получает все атрибуты и методы первого класса. Исходный
класс
называется
родителем
, а новый класс —
потомком
. Класс-потомок наследует
атрибуты и методы родителя, но при этом также может определять собственные
атрибуты и методы.
Метод __init__() класса-потомка
Первое, что делает Python при создании экземпляра класса-потомка, — присваивает
значения всем атрибутам класса-родителя. Для этого методу
__init__()
класса-по-
томка необходима помощь со стороны родителя.
Например, попробуем построить модель электромобиля. Электромобиль пред-
ставляет собой специализированную разновидность автомобиля, поэтому новый
класс
ElectricCar
можно создать на базе класса
Car
, написанного ранее. Тогда
нам останется добавить в него код атрибутов и поведения, относящегося только
к электромобилям.
Начнем с создания простой версии класса
ElectricCar
, который делает все, что
делает класс
Car
:
electric_car.py
class Car():
"""Простая модель автомобиля."""
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
Наследование
171
def read_odometer(self):
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
self.odometer_reading += miles
class ElectricCar(Car):
"""Представляет
аспекты машины, специфические для электромобилей."""
def __init__(self, make, model, year):
"""Инициализирует атрибуты класса-родителя."""
super().__init__(make, model, year)
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
В точке
строится экземпляр
Car
. При создании класса-потомка класс-родитель
должен быть частью текущего файла, а его определение должно предшествовать
определению класса-потомка в файле. В точке
определяется класс-потомок
ElectricCar
. В определении потомка имя класса-родителя заключается в круглые
скобки. Метод
__init__()
в точке
получает информацию, необходимую для
создания экземпляра
Car
.
Функция
super()
в строке
— специальная функция, которая помогает Python
связать потомка с родителем. Эта строка приказывает Python вызвать метод
__init__()
класса, являющегося родителем
ElectricCar
, в результате чего экзем-
пляр
ElectricCar
получает все атрибуты класса-родителя. Имя
super
происходит
из распространенной терминологии: класс-родитель называется
суперклассом
,
а класс-потомок —
субклассом
.
Чтобы проверить, правильно ли сработало наследование, попробуем создать
электромобиль с такой же информацией, которая передается при создании
обычного экземпляра
Car
. В точке
мы создаем экземпляр класса
ElectricCar
и сохраняем его в
my_tesla
. Эта строка вызывает метод
__init__()
, определен-
ный в
ElectricCar
, который в свою очередь приказывает Python вызвать метод
__init__()
, определенный в классе-родителе
Car
. При вызове передаются аргу-
менты
'tesla'
,
'model
s'
и
2016
.
Кроме
__init__()
класс еще не содержит никаких атрибутов или методов, специ-
фических для электромобилей. Пока мы просто убеждаемся в том, что класс
электромобиля
содержит все поведение, присущее классу автомобиля:
2016 Tesla Model S
Экземпляр
ElectricCar
работает так же, как экземпляр
Car
; можно переходить
к определению
атрибутов и методов, специфических для электромобилей.