УПРАЖНЕНИЯ
8-15 . Печать моделей: выделите функции примера print_models .py в отдельный файл с име-
нем printing_functions .py . Разместите команду import в начале файла print_models .py и из-
мените файл так, чтобы в нем использовались импортированные функции .
Итоги 159
8-16 . Импортирование: возьмите за основу одну из написанных вами программ с одной
функцией . Сохраните эту функцию в отдельном файле . Импортируйте функцию в файл
основной программы и вызовите функцию каждым из следующих способов:
import имя_модуля
from имя_модуля import имя_функции
from имя_модуля import имя_функции as псевдоним
import имя_модуля as псевдоним
from имя_модуля import *
8-17 . Стилевое оформление функций: выберите любые три программы, написанные для
этой главы . Убедитесь в том, что в них соблюдаются рекомендации стилевого оформления,
представленные в этом разделе .
Итоги
В этой главе вы научились писать функции и передавать аргументы, в которых
функциям сообщается информация, необходимая для их работы. Вы узнали, как
использовать позиционные и именованные аргументы и как передать функции про-
извольное количество аргументов. Вы видели функции, которые выводят данные,
и функции, которые возвращают значения. Вы научились использовать функции
со списками, словарями, командами
if
и циклами
while
. Также вы научились со-
хранять функции в отдельных файлах, называемых модулями, чтобы код ваших
программ стал проще и понятнее. Глава завершается рекомендациями по стилевому
оформлению функций, чтобы ваши программы были хорошо структурированы
и легко читались вами и другими разработчиками.
Каждый программист должен стремиться к написанию простого кода, который справ-
ляется с поставленной задачей, и функции помогают вам в этом. Вы сможете писать
блоки кода и оставлять их на будущее. Когда вы знаете, что функция правильно справ-
ляется со своей задачей, считайте, что она работает, и переходите к следующей задаче.
В программе с использованием функций единожды написанный код может заново
использоваться столько раз, сколько потребуется. Чтобы выполнить код, содержа-
щийся в функции, достаточно написать всего одну строку с вызовом, а функция
сделает все остальное. Если же потребуется модифицировать поведение функции,
достаточно внести изменения всего в одном месте; они вступят в силу повсюду, где
вызывается эта функция.
С функциями ваши программы проще читаются, а хорошо выбранные имена
функций описывают, что делает та или иная часть программы. Прочитав серию
вызовов функций, вы гораздо быстрее поймете, что делает функция, чем при чтении
длинной серии программных блоков.
Функции также упрощают тестирование и отладку кода. Когда основная работа про-
граммы выполняется набором функций, каждая из которых решает одну конкретную
задачу, вам будет намного проще организовать тестирование и сопровождение вашего
кода. Напишите отдельную программу, которая вызывает каждую функцию и про-
веряет ее работоспособность во всех типичных ситуациях. В этом случае вы можете
быть уверены в том, что ваши функции всегда работают правильно.
В главе 9 вы научитесь писать классы. Классы объединяют функции и данные
в один удобный пакет, с которым вы можете работать гибко и эффективно.
9
Классы
Объектно-ориентированное программирование по праву считается одной из
самых эффективных методологий создания программных продуктов. В объ-
ектно-ориентированном программировании вы пишете классы, описывающие
реально существующие предметы и ситуации, а затем создаете объекты на основе
этих описаний. При написании класса определяется общее поведение для целой
категории объектов.
Когда вы создаете конкретные объекты на базе этих классов, каждый объект
автоматически наделяется общим поведением; после этого вы можете наделить
каждый объект уникальными особенностями на свой выбор. Просто невероятно,
насколько хорошо реальные ситуации моделируются в объектно-ориентированном
программировании.
Создание объекта на основе класса называется созданием экземпляра; таким об-
разом, вы работаете с экземплярами класса. В этой главе вы будете писать классы
и создавать экземпляры этих классов. Вы укажете, какая информация может
храниться в экземплярах, и определите действия, которые могут выполняться
с экземплярами.
Также вы будете писать классы, расширяющие функциональность существу-
ющих классов; это позволяет организовать эффективное совместное использо-
вание кода похожими классами. Вы будете сохранять классы в модулях и импор-
тировать классы, написанные другими программистами, в ваши программные
файлы.
С хорошим пониманием объектно-ориентированного программирования вы взгля-
нете на мир с точки зрения программиста. Вам будет проще понять свой код —
увидеть не только то, что происходит в каждой его строке, но и более масштабные
концепции, лежащие в его основе. Логика, заложенная в основу классов, научит
вас мыслить последовательно, чтобы ваши программы эффективно решали прак-
тически любые задачи, с которыми вы можете столкнуться.
Кроме того, классы упрощают жизнь вам и другим программистам, с которыми вам
придется работать совместно над более серьезными проектами. Когда вы и другие
программисты пишете код, базирующийся на сходной логике, вам проще понять
код друг друга. Ваши программы будут понятны коллегам, и в результате все вы
сможете добиться лучших результатов.
Создание и использование класса 161
Создание и использование класса
Классы позволяют моделировать практически все что угодно. Начнем с написания
простого класса
Dog
, представляющего собаку — не какую-то конкретную, а собаку
вообще. Что мы знаем о собаках? У них есть кличка и возраст. Также известно, что
большинство собак умеют садиться и перекатываться по команде. Эти два вида
информации (кличка и возраст) и два вида поведения (сидеть и перекатываться)
будут включены в класс
Dog
, потому что они являются общими для большинства
собак. Класс сообщает Python, как создать объект, представляющий собаку. По-
сле того как класс будет написан, мы используем его для создания экземпляров,
каждый из которых представляет одну конкретную собаку.
Создание класса Dog
В каждом экземпляре, созданном на основе класса
Dog
, будет храниться кличка
и возраст; кроме того, в нем будут присутствовать методы
sit()
и
roll_over()
:
dog.py
class Dog():
"""Простая модель собаки."""
def __init__(self, name, age):
"""Инициализирует атрибуты name и age."""
self.name = name
self.age = age
def sit(self):
"""Собака садится по команде."""
print(self.name.title() + " is now sitting.")
def roll_over(self):
"""Собака перекатывается по команде."""
print(self.name.title() + " rolled over!")
В этом коде есть много мест, заслуживающих вашего внимания, но не беспокойтесь.
Эта структура неоднократно встретится вам в этой главе, и вы еще успеете к ней
привыкнуть. В точке определяется класс с именем
Dog
. По общепринятым согла-
шениям имена, начинающиеся с символа верхнего регистра, в Python обозначают
классы. Круглые скобки в определении класса пусты, потому что класс создается
с нуля. В точке приведена строка документации с кратким описанием класса.
Метод __init__()
Функция, являющаяся частью класса, называется методом. Все, что вы узнали
ранее о функциях, также относится и к методам; единственное практическое раз-
личие — способ вызова методов. Метод
__init__()
в точке — специальный метод,
который автоматически выполняется при создании каждого нового экземпляра
на базе класса
Dog
. Имя метода начинается и заканчивается двумя символами
подчеркивания; эта схема предотвращает конфликты имен стандартных методов
Python и методов ваших классов.
162 Глава 9 • Классы
Метод
__init__()
определяется с тремя параметрами:
self
,
name
и
age
. Пара-
метр
self
обязателен в определении метода; он должен предшествовать всем
остальным параметрам. Он должен быть включен в определение для того, чтобы
при будущем вызове метода
__init__()
(для создания экземпляра
Dog
) автомати-
чески передавался аргумент
self
. При каждом вызове метода, связанного с клас-
сом, автоматически передается
self
— ссылка на экземпляр; она предоставляет
конкретному экземпляру доступ к атрибутам и методам класса. Когда вы создаете
экземпляр
Dog
, Python вызывает метод
__init__()
из класса
Dog
. Мы передаем
Dog()
кличку и возраст в аргументах; значение
self
передается автоматически, так
что его передавать не нужно. Каждый раз, когда вы захотите создать экземпляр
на основе класса
Dog
, необходимо предоставить значения только двух последних
аргументов
name
и
age
.
Каждая из двух переменных, определяемых в точке , имеет префикс
self
. Лю-
бая переменная с префиксом
self
доступна для каждого метода в классе, и вы
также сможете обращаться к этим переменным в каждом экземпляре, созданном
на основе класса. Конструкция
self.name
=
name
берет значение, хранящееся
в параметре
name
, и сохраняет его в переменной
name
, которая затем связыва-
ется с создаваемым экземпляром. Процесс также повторяется с
self.age
=
age
.
Переменные, к которым вы обращаетесь через экземпляры, тоже называются
атрибутами.
В классе
Dog
также определяются два метода:
sit()
и
roll_over()
. Так как
этим методам не нужна дополнительная информация (кличка или возраст), они
определяются с единственным параметром
self
. Экземпляры, которые будут
созданы позднее, смогут вызывать эти методы. Пока методы
sit()
и
roll_over()
ограничиваются простым выводом сообщения о том, что собака садится или
перекатывается. Тем не менее концепцию легко расширить для практического
применения: если бы этот класс был частью компьютерной игры, то эти методы
вполне могли бы содержать код для создания анимации садящейся или пере-
катывающейся собаки. А если бы класс был написан для управления роботом,
то методы могли бы управлять механизмами, заставляющими робота-собаку
выполнить соответствующую команду.
Создание классов в Python 2 .7
При создании классов в Python 2.7 необходимо внести одно незначительное из-
менение — заключить в круглые скобки ключевое слово
object
:
class ClassName(object):
...
В этом случае поведение классов Python 2.7 будет приближено к поведению клас-
сов Python 3, что упрощает вашу работу в целом.
Скажем, в Python 2.7 класс
Dog
будет определяться следующим образом:
class Dog(object):
...
Создание и использование класса 163
Создание экземпляра класса
Считайте, что класс — это своего рода инструкция по созданию экземпляров. Со-
ответственно, класс
Dog
— инструкция по созданию экземпляров, представляющих
конкретных собак.
Создадим экземпляр, представляющий конкретную собаку:
class Dog():
...
my_dog = Dog('willie', 6)
print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.")
Использованный в данном случае класс
Dog
был написан в предыдущем при-
мере. В точке мы приказываем Python создать экземпляр собаки с кличкой
'willie'
и возрастом 6. В процессе обработки этой строки Python вызывает ме-
тод
__init__()
класса
Dog
с аргументами
'willie'
и 6. Метод
__init__()
создает
экземпляр, представляющий конкретную собаку, и присваивает его атрибутам
name
и
age
переданные значения. Метод
__init__()
не содержит явной команды
return
,
но Python автоматически возвращает экземпляр, представляющий собаку. Этот
экземпляр сохраняется в переменной
my_dog
. Здесь нелишне вспомнить соглаше-
ния по записи имен: обычно считается, что имя, начинающееся с символа верхнего
регистра (например,
Dog
), обозначает класс, а имя, записанное в нижнем регистре
(например,
my_dog
), обозначает отдельный экземпляр, созданный на базе класса.
Обращение к атрибутам
Для обращения к атрибутам экземпляра используется «точечная» запись. В стро-
ке мы обращаемся к значению атрибута
name
экземпляра
my_dog
:
my_dog.name
Точечная запись часто используется в Python. Этот синтаксис показывает, как
Python ищет значения атрибутов. В данном случае Python обращается к экзем-
пляру
my_dog
и ищет атрибут
name
, связанный с экземпляром
my_dog
. Это тот же
атрибут, который обозначался
self.name
в классе
Dog
. В точке тот же прием ис-
пользуется для работы с атрибутом
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
:
164 Глава 9 • Классы
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
. Вы можете создать сколько
угодно экземпляров одного класса при условии, что эти экземпляры хранятся
Работа с классами и экземплярами 165
в переменных с разными именами или занимают разные позиции в списке или
словаре:
Достарыңызбен бөлісу: |