УПРАЖНЕНИЯ
9-1 . Ресторан: создайте класс с именем Restaurant . Метод __init__() класса Restaurant дол-
жен содержать два атрибута: restaurant_name и cuisine_type . Создайте метод describe_
restaurant(), который выводит два атрибута, и метод open_restaurant(), который выводит
сообщение о том, что ресторан открыт .
Создайте на основе своего класса экземпляр с именем restaurant . Выведите два атрибута по
отдельности, затем вызовите оба метода .
9-2 . Три ресторана: начните с класса из упражнения 9-1 . Создайте три разных экземпляра,
вызовите для каждого экземпляра метод describe_restaurant() .
9-3 . Пользователи: создайте класс с именем User . Создайте два атрибута first_name и last_
name, а затем еще несколько атрибутов, которые обычно хранятся в профиле пользова-
теля . Напишите метод describe_user(), который выводит сводку с информацией о пользо-
вателе . Создайте еще один метод greet_user() для вывода персонального приветствия для
пользователя .
Создайте несколько экземпляров, представляющих разных пользователей . Вызовите оба
метода для каждого пользователя .
Работа с классами и экземплярами
Классы могут использоваться для моделирования многих реальных ситуаций. По-
сле того как класс будет написан, разработчик проводит бульшую часть времени
за работой с экземплярами, созданными на основе этого класса. Одной из первых
задач станет изменение атрибутов, связанных с конкретным экземпляром. Атрибу-
ты экземпляра можно изменять напрямую или же написать методы, изменяющие
атрибуты по особым правилам.
Класс Car
Напишем класс, представляющий автомобиль. Этот класс будет содержать инфор-
мацию о типе машины, а также метод для вывода краткого описания:
car.py
class Car():
"""Простая модель автомобиля."""
def __init__(self, make, model, year):
"""Инициализирует атрибуты описания автомобиля."""
self.make = make
self.model = model
self.year = year
def get_descriptive_name(self):
"""Возвращает аккуратно отформатированное описание."""
long_name = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
166 Глава 9 • Классы
В точке в классе
Car
определяется метод
__init__()
; его список параметров на-
чинается с
self
, как и в классе
Dog
. За ним следуют еще три параметра:
make
,
model
и
year
. Метод
__init__()
получает эти параметры и сохраняет их в атрибутах, ко-
торые будут связаны с экземплярами, созданными на основе класса. При создании
нового экземпляра
Car
необходимо указать фирму-производителя, модель и год
выпуска для данного экземпляра.
В точке определяется метод
get_descriptive_name()
, который объединяет год
выпуска, фирму-производителя и модель в одну строку с описанием. Это избавит
вас от необходимости выводить значение каждого атрибута по отдельности. Для
работы со значениями атрибутов в этом методе используется синтаксис
self.make
,
self.model
и
self.year
.
В точке создается экземпляр класса
Car
, который сохраняется в переменной
my_new_car
. Затем вызов метода
get_descriptive_name()
показывает, с какой ма-
шиной работает программа:
2016 Audi A4
Чтобы класс был более интересным, добавим атрибут, изменяющийся со време-
нем, — в нем будет храниться пробег машины в милях.
Назначение атрибуту значения по умолчанию
Каждый атрибут класса должен иметь исходное значение, даже если оно равно
0 или пустой строке. В некоторых случаях (например, при задании значений по
умолчанию) это исходное значение есть смысл задавать в теле метода
__init__()
;
в таком случае передавать параметр для этого атрибута при создании объекта
не обязательно.
Добавим атрибут с именем
odometer_reading
, исходное значение которого всегда
равно 0. Также в класс будет включен метод
read_odometer()
для чтения текущих
показаний одометра:
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):
...
def read_odometer(self):
"""Выводит пробег машины в милях."""
print("This car has " + str(self.odometer_reading) + " miles on it.")
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()
Работа с классами и экземплярами 167
Когда Python вызывает метод
__init__()
для создания нового экземпляра, этот
метод сохраняет фирму-производителя, модель и год выпуска в атрибутах, как
и в предыдущем случае. Затем Python создает новый атрибут с именем
odometer_
reading
и присваивает ему исходное значение 0 . Также в класс добавляется
новый метод
read_odometer()
, который упрощает чтение пробега машины
в милях.
Сразу же после создания машины ее пробег равен 0:
2016 Audi A4
This car has 0 miles on it.
Впрочем, у продаваемых машин одометр редко показывает ровно 0, поэтому нам
понадобится способ изменения значения этого атрибута.
Изменение значений атрибутов
Значение атрибута можно изменить одним из трех способов: изменить его прямо
в экземпляре, задать значение при помощи метода или изменить его с приращением
(то есть прибавлением определенной величины) при помощи метода. Рассмотрим
все эти способы.
Прямое изменение значения атрибута
Чтобы изменить значение атрибута, проще всего обратиться к нему прямо через эк-
земпляр. В следующем примере на одометре напрямую выставляется значение 23:
class Car():
...
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
В точке точечная запись используется для обращения к атрибуту
odometer_
reading
экземпляра и прямого присваивания его значения. Эта строка приказывает
Python взять экземпляр
my_new_car
, найти связанный с ним атрибут
odometer_
reading
и задать значение атрибута равным 23:
2016 Audi A4
This car has 23 miles on it.
Иногда подобные прямые обращения к атрибутам допустимы, но чаще разработчик
пишет вспомогательный метод, который изменяет значение за него.
Изменение значения атрибута с использованием метода
В класс можно включить методы, которые изменяют некоторые атрибуты за вас.
Вместо того чтобы изменять атрибут напрямую, вы передаете новое значение ме-
тоду, который берет обновление атрибута на себя.
168 Глава 9 • Классы
В следующем примере в класс включается метод
update_odometer()
для изменения
показаний одометра:
class Car():
...
def update_odometer(self, mileage):
"""Устанавливает заданное значение на одометре."""
self.odometer_reading = mileage
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.update_odometer(23)
my_new_car.read_odometer()
Класс
Car
почти не изменился, в нем только добавился метод
update_odometer()
.
Этот метод получает пробег в милях и сохраняет его в
self.odometer_reading
.
В точке мы вызываем метод
update_odometer()
и передаем ему значение 23
в аргументе (соответствующем параметру
mileage
в определении метода). Метод
устанавливает на одометре значение 23, а метод
read_odometer()
выводит текущие
показания:
2016 Audi A4
This car has 23 miles on it.
Метод
update_odometer()
можно расширить так, чтобы при каждом изменении
показаний одометра выполнялась некоторая дополнительная работа. Добавим
проверку, которая гарантирует, что никто не будет пытаться сбрасывать показания
одометра:
class Car():
...
def update_odometer(self, mileage):
"""
Устанавливает на одометре заданное значение.
При попытке обратной подкрутки изменение отклоняется.
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
Теперь
update_odometer()
проверяет новое значение перед изменением атрибута.
Если новое значение
mileage
больше или равно текущего,
self.odometer_reading
,
показания одометра можно обновить новым значением . Если же новое значение
меньше текущего, вы получите предупреждение о недопустимости обратной под-
крутки .
Изменение значения атрибута с приращением
Иногда значение атрибута требуется изменить с заданным приращением (вме-
сто того чтобы присваивать атрибуту произвольное новое значение). Допустим,
Работа с классами и экземплярами 169
вы купили подержанную машину и проехали на ней 100 миль. Следующий метод
получает величину приращения и прибавляет ее к текущим показаниям одометра:
class Car():
...
def update_odometer(self, mileage):
--snip--
def increment_odometer(self, miles):
"""Увеличивает показания одометра с заданным приращением."""
self.odometer_reading += miles
my_used_car = Car('subaru', 'outback', 2013)
print(my_used_car.get_descriptive_name())
my_used_car.update_odometer(23500)
my_used_car.read_odometer()
my_used_car.increment_odometer(100)
my_used_car.read_odometer()
Новый метод
increment_odometer()
в точке получает расстояние в милях
и прибавляет его к
self.odometer_reading
. В точке создается экземпляр
my_used_car
. Мы инициализируем показания его одометра значением 23 500;
для этого вызывается метод
update_odometer()
, которому передается значение
23500 . В точке вызывается метод
increment_odometer()
, которому передает-
ся значение 100, чтобы увеличить показания одометра на 100 миль, пройденные
с момента покупки:
2013 Subaru Outback
This car has 23500 miles on it.
This car has 23600 miles on it.
При желании можно легко усовершенствовать этот метод, чтобы он отклонял
отрицательные приращения; тем самым вы предотвратите обратную подкрутку
одометра.
Достарыңызбен бөлісу: |