Считайте, что класс — это своего рода инструкция по созданию экземпляров. Соответственно, класс Dog — инструкция по созданию экземпляров, представляющих конкретных собак.
Создадим экземпляр, представляющий конкретную собаку:
class Dog():
. ....
(1) my_dog = Dog('willie', 6)
(2)print("My dog's name is " + my_dog.name.title() + ".")
(3)print("My dog is " + str(my_dog.age) + " years old.")
Использованный в данном случае класс Dog был написан в предыдущем примере. В точке (1) мы приказываем Python создать экземпляр собаки с кличкой 'willie' и возрастом 6. В процессе обработки этой строки Python вызывает метод __init__() класса Dog с аргументами 'willie' и 6. Метод __init__() создает экземпляр, представляющий конкретную собаку, и присваивает его атрибутам name и age переданные значения. Метод __init__() не содержит явной команды return, но Python автоматически возвращает экземпляр, представляющий собаку. Этот экземпляр сохраняется в переменной my_dog. Здесь нелишне вспомнить соглашения по записи имен: обычно считается, что имя, начинающееся с символа верхнего регистра (например, Dog), обозначает класс, а имя, записанное в нижнем регистре (например, my_dog), обозначает отдельный экземпляр, созданный на базе класса.
Обращение к атрибутам
Для обращения к атрибутам экземпляра используется «точечная» запись. В строке (2) мы обращаемся к значению атрибута name экземпляра my_dog:
my_dog.name
Точечная запись часто используется в Python. Этот синтаксис показывает, как Python ищет значения атрибутов. В данном случае Python обращается к экземпляру my_dog и ищет атрибут name, связанный с экземпляром my_dog. Это тот же атрибут, который обозначался self.name в классе Dog. В точке (3) тот же прием используется для работы с атрибутом age. В первой команде print вызов my_dog.name.title() записывает 'willie' (значение атрибута name экземпляра my_dog) с символа верхнего регистра. Во второй команде print вызов str(my_dog.age) преобразует 6, значение атрибута age экземпляра my_dog, в строку.
Пример выводит сводку известных фактов о my_dog:
My dog's name is Willie.
My dog is 6 years old.
Вызов методов
После создания экземпляра на основе класса Dog можно применять точечную запись для вызова любых методов, определенных в Dog:
class Dog():
...
my_dog = Dog('willie', 6)
my_dog.sit()
my_dog.roll_over()
Чтобы вызвать метод, укажите экземпляр (в данном случае my_dog) и вызываемый метод, разделив их точкой. В ходе обработки my_dog.sit() Python ищет метод sit() в классе Dog и выполняет его код. Строка my_dog.roll_over() интерпретируется аналогичным образом.
Теперь экземпляр послушно выполняет полученные команды:
Willie is now sitting.
Willie rolled over!
Это очень полезный синтаксис. Если атрибутам и методам были присвоены содержательные имена (например, name, age, sit() и roll_over()), разработчик сможет легко понять, что делает блок кода, — даже если он видит этот блок впервые.
Создание нескольких экземпляров
На основе класса можно создать столько экземпляров, сколько вам потребуется. Создадим второй экземпляр Dog с именем your_dog:
class Dog():
...
my_dog = Dog('willie', 6)
your_dog = Dog('lucy', 3)
print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.")
my_dog.sit()
print("\nYour dog's name is " + your_dog.name.title() + ".")
print("Your dog is " + str(your_dog.age) + " years old.")
your_dog.sit()
В этом примере создаются два экземпляра с именами Willie и Lucy. Каждый экземпляр обладает своим набором атрибутов и способен выполнять действия из общего набора:
My dog's name is Willie.
My dog is 6 years old.
Willie is now sitting.
Your dog's name is Lucy.
Your dog is 3 years old.
Lucy is now sitting.
Даже если второй собаке будут назначены те же имя и возраст, Python все равно создаст отдельный экземпляр класса Dog. Вы можете создать сколько угодно экземпляров одного класса при условии, что эти экземпляры хранятся в переменных с разными именами или занимают разные позиции в списке или словаре:
Упражнения
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() для вывода персонального приветствия для пользователя.