Файл: Книга на вашем родном языке 6 2 Переводы 7 1 Доступные переводы переводы 7 3 Предисловие 16.pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 10.01.2024
Просмотров: 233
Скачиваний: 2
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
else
:
print
(
'Создание резервной копии НЕ УДАЛОСЬ'
)
7
bug fixing – устранение «багов», исправление ошибок (прим.перев)
13.5. Четвёртая версия
105
A Byte of Python (Russian), Версия 2.02
Вывод:
$ python3 backup_ver4.py
Введите комментарий --> added new examples
Резервная копия успешно создана в E:\Backup\20080702\202836_added_new_
,
→
examples.zip
$ python3 backup_ver4.py
Введите комментарий -->
Резервная копия успешно создана в E:\Backup\20080702\202839.zip
Как это работает:
Теперь эта программа работает! Давайте просмотрим все улучшения, сделан- ные нами для версии 3. Мы запрашиваем пользовательский комментарий при помощи функции input
, а затем проверяем, ввёл ли пользователь что-либо,
определяя длину введённой строки функцией len
. Если пользователь просто нажал
ENTER
, не вводя никакого текста (может быть, это было регулярное со- здание резервной копии, или никаких особых изменений внесено не было),
мы продолжаем так же, как делали до сих пор.
Если же комментарий был введён, он добавляется к имени zip-архива перед расширением
.zip
. Обратите внимание, что мы заменяем пробелы в коммен- тарии подчёркиваниями: управлять файлами без пробелов в именах намного легче.
13.6 Дополнительные усовершенствования
Четвёртая версия – вполне удовлетворительный рабочий сценарий для большинства пользователей, однако нет пределов совершенства. Например, в программу можно доба- вить уровень подробности
8
вывода, чтобы при указании параметра «
-v
» она становилась более «разговорчивой».
Ещё одним возможным улучшением была бы возможность передавать сценарию другие файлы и каталоги прямо в командной строке. Эти имена можно получать из списка sys.
argv и добавлять к нашему списку source при помощи метода extend класса list
Наиболее важным усовершенствованием было бы прекращение использования os.
system для создания архивов, а применение вместо него встроенных модулей zipfile или tarfile
. Они являются частью стандартной библиотеки, поэтому всегда доступны для использования без зависимости от внешней программы zip на компьютере.
8
verbosity – англ. «многословность». Применительно к компьютерным программам обозначает степень подробности выводимых программой сообщений, т.е. степень «разговорчивости» программы. Отсюда и название этого параметра (прим.перев)
13.6. Дополнительные усовершенствования
106
A Byte of Python (Russian), Версия 2.02
В приведённых примерах мы использовали способ с os.system для создания резервных копий исключительно в педагогических целях, чтобы пример был достаточно прост для понимания любым читателем, но достаточно реален для того, чтобы делать что-то полез- ное.
Попробуйте написать пятую версию с использованием модуля zipfile вместо вызова os.
system
13.7 Процесс разработки программного обеспече- ния
В процессе создания программы мы прошли через несколько стадий. Эти стадии можно свести примерно в такой список:
• Что (Анализ)
• Как (Проектирование)
• Создание (Реализация)
• Тестирование (Тестирование и Отладка)
• Использование (Развёртывание и Оперирование)
• Поддержка (Усовершенствование)
Процедура, которую мы прошли при написании сценария создания резервных копий ре- комендуется и для других программ: Проведите анализ и проектирование. Начните ре- ализацию с простейшей версии. Протестируйте и отладьте её. Попользуйтесь ею, чтобы убедиться, что она работает, как ожидалось. После этого добавляйте любые необходимые функции, повторяя цикл «Создание-Тестирование-Использование» столько раз, сколько потребуется. Помните, Программы выращиваются, а не строятся.
13.8 Резюме
Мы увидели, как создавать свои собственные программы/сценарии на Python, а также различные стадии написания программ. На данном этапе вам будет полезно создать соб- ственную программу по такому рецепту, как мы это делали в настоящей главе, чтобы лучше привыкнуть к Python, равно как и к решению задач.
Далее мы обсудим объектно-ориентированное программирование.
13.7. Процесс разработки программного обеспечения
107
Объектно-ориентированное
программирование
До сих пор наши программы состояли из функций, т.е. блоков выражений, которые мани- пулируют данными. Это называется процедурно-ориентированным стилем программиро- вания. Существует и другой способ организации программ: объединять данные и функ- ционал внутри некоего объекта. Это называется объектно-ориентированной парадигмой программирования. В большинстве случаев можно ограничиться процедурным програм- мированием, а при написании большой программы или если решение конкретной зада- чи того требует, можно переходить к техникам объектно-ориентированного программи- рования.
Два основных аспекта объектно-ориентированного программирования – классы и объ- екты. Класс создаёт новый тип, а объекты являются экземплярами класса. Аналогично,
когда мы говорим о «переменных типа int
», это означает, что переменные, которые хра- нят целочисленные значения, являются экземплярами (объектами) класса int
Замечание для программистов на статических языках
Обратите внимание, что даже целые числа рассматриваются как объекты (класса int
),
в отличие от C++ и Java (до версии 1.5), где целые числа являются примитивами. См.
help(int)
для более детального описания этого класса. Программисты на C# и Java 1.5
могут заметить сходство с концепцией упаковки и распаковки
1
Объекты могут хранить данные в обычных переменных, которые принадлежат объек- ту. Переменные, принадлежащие объекту или классу, называют полями. Объекты могут также обладать функционалом, т.е. иметь функции, принадлежащие классу. Такие функ- ции принято называть методами класса. Эта терминология важна, так как она помогает нам отличать независимые функции и переменные от тех, что принадлежат классу или объекту. Всё вместе (поля и методы) принято называть атрибутами класса.
Поля бывают двух типов: они могут принадлежать каждому отдельному экземпляру объ- екта класса или всему классу. Они называются переменными экземпляра и перемен-
ными класса соответственно.
1
boxing and unboxing
108
A Byte of Python (Russian), Версия 2.02
Класс создаётся ключевым словом class
. Поля и методы класса записываются в блоке кода с отступом.
14.1 self
Методы класса имеют одно отличие от обычных функций: они должны иметь дополни- тельно имя, добавляемое к началу списка параметров. Однако, при вызове метода никако- го значения этому параметру присваивать не нужно – его укажет Python. Эта переменная указывает на сам объект экземпляра класса, и по традиции она называется self
2
Хотя этому параметру можно дать любое имя, настоятельно рекомендуется использовать только имя self
; использование любого другого имени не приветствуется. Есть много до- стоинств использования стандартного имени: во-первых, любой человек, просматриваю- щий вашу программу, легко узнает его; во-вторых, некоторые специализированные Ин- тегрированные среды разработки (IDE) изначально рассчитаны на использование self
Замечание для программистов на C++, Java и C#
self в Python эквивалентно указателю this в C++ и ссылке this в Java и C#.
Вы, должно быть, удивляетесь, как Python присваивает значение self и почему вам не нужно указывать это значение самостоятельно. Поясним это на примере. Предположим,
у нас есть класс с именем
MyClass и экземпляр этого класса с именем myobject
. При вызове метода этого объекта, например, «
myobject.method(arg1, arg2)
», Python ав- томатически превращает это в «
MyClass.method(myobject, arg1, arg2)
» – в этом и состоит смысл self
Это также означает, что если какой-либо метод не принимает аргументов, у него всё равно будет один аргумент –
self
14.2 Классы
Простейший класс показан в следующем примере (сохраните как simplestclass.py
).
class
Person
:
pass
# Пустой блок
p
=
Person()
print
(p)
Вывод:
2
self – англ. «сам» (прим.перев.)
14.1. self
109
A Byte of Python (Russian), Версия 2.02
$ python3 simplestclass.py
<__main__.Person object at 0x019F85F0>
Как это работает:
Мы создаём новый класс при помощи оператора class и имени класса. За этим следует блок выражений, формирующих тело класса. В данном случае блок у нас пуст, на что указывает оператор pass
Далее мы создаём объект-экземпляр класса, записывая имя класса со скобка- ми. (Мы узнаем больше о
реализации
в следующем разделе). Для проверки мы выясняем тип переменной, просто выводя её на экран. Так мы видим, что у нас есть экземпляр класса
Person в модуле
__main__
Обратите внимание, что выводится также и адрес в памяти компьютера, где хранится ваш объект. На вашем компьютере адрес будет другим, так как
Python хранит объекты там, где имеется свободное место.
14.3 Методы объектов
Итак, мы выяснили что классы/объекты могут иметь методы, представляющие собой функции, за исключением дополнительной переменной self
. А теперь давайте рассмот- рим пример (сохраните как method.py
).
class
Person
:
def
sayHi
(
self
):
print
(
'Привет! Как дела?'
)
p
=
Person()
p sayHi()
# Этот короткий пример можно также записать как Person().sayHi()
Вывод:
$ python3 method.py
Привет! Как дела?
Как это работает:
Здесь мы видим self в действии. Обратите внимание, что метод sayHi не принимает параметров, но тем не менее, имеет self в определении функции.
14.3. Методы объектов
110
A Byte of Python (Russian), Версия 2.02 14.4 Метод
__init__
Существует много методов, играющих специальную роль в классах Python. Сейчас мы увидим значительность метода
__init__
Метод
__init__
запускается, как только объект класса реализуется. Этот метод полезен для осуществления разного рода инициализации, необходимой для данного объекта. Об- ратите внимание на двойные подчёркивания в начале и в конце имени.
Пример: (сохраните как oop_init.py
)
class
Person
:
def
__init__
(
self
, name):
self name
=
name
def
say_hi
(
self
):
print
(
'Привет! Меня зовут'
,
self name)
p
=
Person(
'Swaroop'
)
p say_hi()
# Предыдущие 2 строки можно
# Person('Swaroop').say_hi()
Вывод:
$ python oop_init.py
Привет! Меня зовут Swaroop
Как это работает:
Здесь мы определяем метод
__init__
так, чтобы он принимал параметр name
(наряду с обычным self
). Далее мы создаём новое поле с именем name
. Об- ратите внимание, что это две разные переменные, даже несмотря на то, что они обе названы name
. Это не проблема, так как точка в выражении self.
name обозначает, что существует нечто с именем «name», являющееся частью объекта «self», и другое name
– локальная переменная. Поскольку мы в явном виде указываем, к которому имени мы обращаемся, путаницы не возникнет.
Для создания нового экземпляра p
класса
Person мы указываем имя класса,
после которого – аргументы в скобках:
p = Person('Swaroop')
Метод
__init__
мы при этом не вызываем явным образом. В этом и заклю- чается специальная роль данного метода.
После этого мы получаем возможность использовать поле self.name в наших методах, что и продемонстрировано в методе say_hi
14.4. Метод
__init__
111
A Byte of Python (Russian), Версия 2.02 14.5 Переменные класса и объекта
Функциональную часть классов и объектов (т.е. методы) мы обсудили, теперь давайте ознакомимся с частью данных. Данные, т.е. поля, являются не чем иным, как обычны- ми переменными, заключёнными в пространствах имён классов и объектов. Это означа- ет, что их имена действительны только в контексте этих классов или объектов. Отсюда и название «пространство имён».
Существует два типа полей: переменные класса и переменные объекта, которые разли- чаются в зависимости от того, принадлежит ли переменная классу или объекту соответ- ственно.
Переменные класса разделяемы – доступ к ним могут получать все экземпляры этого клас- са. Переменная класса существует только одна, поэтому когда любой из объектов изме- няет переменную класса, это изменение отразится и во всех остальных экземплярах того же класса.
Переменные объекта принадлежат каждому отдельному экземпляру класса. В этом случае у каждого объекта есть своя собственная копия поля, т.е. не разделяемая и никоим образом не связанная с другими такими же полями в других экземплярах. Это легко понять на примере (сохраните как objvar.py
):
class
Robot
:
'''Представляет робота с именем.'''
# Переменная класса, содержащая количество роботов
population
=
0
def
__init__
(
self
, name):
'''Инициализация данных.'''
self name
=
name print
(
'(Инициализация
{0}
)'
format(
self name))
# При создании этой личности, робот добавляется
# к переменной 'population'
Robot population
+=
1
def
__del__
(
self
):
'''Я умираю.'''
print
(
'
{0}
уничтожается!'
format(
self name))
Robot population
-=
1
if
Robot population
==
0
:
print
(
'
{0}
был последним.'
format(
self name))
else
:
print
(
'Осталось
{0:d}
работающих роботов.'
format(
\
(продолжение на следующей странице)
14.5. Переменные класса и объекта
112
A Byte of Python (Russian), Версия 2.02
(продолжение с предыдущей страницы)
Robot population))
def
sayHi
(
self
):
'''Приветствие робота.
Да, они это могут.'''
print
(
'Приветствую! Мои хозяева называют меня
{0}
.'
format(
self name))
def
howMany
():
'''Выводит численность роботов.'''
print
(
'У нас
{0:d}
роботов.'
format(Robot population))
howMany
=
staticmethod
(howMany)
droid1
=
Robot(
'R2-D2'
)
droid1
sayHi()
Robot howMany()
droid2
=
Robot(
'C-3PO'
)
droid2
sayHi()
Robot howMany()
print
(
"
\nЗдесь роботы могут проделать какую-то работу.\n"
)
print
(
"Роботы закончили свою работу. Давайте уничтожим их."
)
del
droid1
del
droid2
Robot howMany()
Вывод:
$ python3 objvar.py
(Инициализация R2-D2)
Приветствую! Мои хозяева называют меня R2-D2.
У нас 1 роботов.
(Инициализация C-3PO)
Приветствую! Мои хозяева называют меня C-3PO.
У нас 2 роботов.
Здесь роботы могут проделать какую-то работу.
Роботы закончили свою работу. Давайте уничтожим их.
R2-D2 уничтожается!
Осталось 1 работающих роботов.
(продолжение на следующей странице)
14.5. Переменные класса и объекта
113
A Byte of Python (Russian), Версия 2.02
(продолжение с предыдущей страницы)
C-3PO уничтожается!
C-3PO был последним.
У нас 0 роботов.
Как это работает:
Это длинный пример, но он помогает продемонстрировать природу перемен- ных класса и объекта. Здесь population принадлежит классу
Robot
, и поэто- му является переменной класса. Переменная name принадлежит объекту (ей присваивается значение при помощи self
), и поэтому является переменной объекта.
Таким образом, мы обращаемся к переменной класса population как
Robot.
population
, а не self.population
. К переменной же объекта name во всех методах этого объекта мы обращаемся при помощи обозначения self.name
Помните об этой простой разнице между переменными класса и объекта. Так- же имейте в виду, что переменная объекта с тем же именем, что и переменная класса, сделает недоступной («спрячет») переменную класса!
Метод howMany принадлежит классу, а не объекту. Это означает, что мы мо- жем определить его как classmethod или staticmethod
, в зависимости от того, нужно ли нам знать, в каком классе мы находимся. Поскольку нам не нужна такая информация, мы воспользуемся staticmethod
Мы могли достичь того же самого, используя декораторы
:
@staticmethod
def
howMany
():
'''Выводит численность роботов.'''
print
(
'У нас
{0:d}
роботов.'
format(Robot population))
Декораторы можно считать неким упрощённым способом вызова явного оператора, как мы видели в этом примере.
Пронаблюдайте, как метод
__init__
используется для инициализации экземпляра
Robot с именем. В этом методе мы увеличиваем счётчик population на 1, так как добав- ляем ещё одного робота. Также заметьте, что значения self.name для каждого объекта свои, что указывает на природу переменных объекта.
Помните, что к переменным и методам самого объекта нужно обращаться, пользуясь
только
self
. Это называется доступом к атрибутам.
В этом примере мы также наблюдали применение строк документации для классов, рав- но как и для методов. Во время выполнения мы можем обращаться к строке документации класса при помощи «
Robot.__doc__
», а к строке документации метода – при помощи
«
Robot.sayHi.__doc__
».
Наряду с методом
__init__
, существует и другой специальный метод
__del__
, который
14.5. Переменные класса и объекта
114
A Byte of Python (Russian), Версия 2.02
вызывается тогда, когда объект собирается умереть, т.е. когда он больше не используется,
и занимаемая им память возвращается операционной системе для другого использова- ния. В этом методе мы просто уменьшаем счётчик
Robot.population на 1.
Метод
__del__
запускается лишь тогда, когда объект перестаёт использоваться, а поэто- му заранее неизвестно, когда именно этот момент наступит. Чтобы увидеть его в действии явно, придётся воспользоваться оператором del
, что мы и сделали выше.
:
(
'Создание резервной копии НЕ УДАЛОСЬ'
)
7
bug fixing – устранение «багов», исправление ошибок (прим.перев)
13.5. Четвёртая версия
105
A Byte of Python (Russian), Версия 2.02
Вывод:
$ python3 backup_ver4.py
Введите комментарий --> added new examples
Резервная копия успешно создана в E:\Backup\20080702\202836_added_new_
,
→
examples.zip
$ python3 backup_ver4.py
Введите комментарий -->
Резервная копия успешно создана в E:\Backup\20080702\202839.zip
Как это работает:
Теперь эта программа работает! Давайте просмотрим все улучшения, сделан- ные нами для версии 3. Мы запрашиваем пользовательский комментарий при помощи функции input
, а затем проверяем, ввёл ли пользователь что-либо,
определяя длину введённой строки функцией len
. Если пользователь просто нажал
ENTER
, не вводя никакого текста (может быть, это было регулярное со- здание резервной копии, или никаких особых изменений внесено не было),
мы продолжаем так же, как делали до сих пор.
Если же комментарий был введён, он добавляется к имени zip-архива перед расширением
.zip
. Обратите внимание, что мы заменяем пробелы в коммен- тарии подчёркиваниями: управлять файлами без пробелов в именах намного легче.
13.6 Дополнительные усовершенствования
Четвёртая версия – вполне удовлетворительный рабочий сценарий для большинства пользователей, однако нет пределов совершенства. Например, в программу можно доба- вить уровень подробности
8
вывода, чтобы при указании параметра «
-v
» она становилась более «разговорчивой».
Ещё одним возможным улучшением была бы возможность передавать сценарию другие файлы и каталоги прямо в командной строке. Эти имена можно получать из списка sys.
argv и добавлять к нашему списку source при помощи метода extend класса list
Наиболее важным усовершенствованием было бы прекращение использования os.
system для создания архивов, а применение вместо него встроенных модулей zipfile или tarfile
. Они являются частью стандартной библиотеки, поэтому всегда доступны для использования без зависимости от внешней программы zip на компьютере.
8
verbosity – англ. «многословность». Применительно к компьютерным программам обозначает степень подробности выводимых программой сообщений, т.е. степень «разговорчивости» программы. Отсюда и название этого параметра (прим.перев)
13.6. Дополнительные усовершенствования
106
A Byte of Python (Russian), Версия 2.02
В приведённых примерах мы использовали способ с os.system для создания резервных копий исключительно в педагогических целях, чтобы пример был достаточно прост для понимания любым читателем, но достаточно реален для того, чтобы делать что-то полез- ное.
Попробуйте написать пятую версию с использованием модуля zipfile вместо вызова os.
system
13.7 Процесс разработки программного обеспече- ния
В процессе создания программы мы прошли через несколько стадий. Эти стадии можно свести примерно в такой список:
• Что (Анализ)
• Как (Проектирование)
• Создание (Реализация)
• Тестирование (Тестирование и Отладка)
• Использование (Развёртывание и Оперирование)
• Поддержка (Усовершенствование)
Процедура, которую мы прошли при написании сценария создания резервных копий ре- комендуется и для других программ: Проведите анализ и проектирование. Начните ре- ализацию с простейшей версии. Протестируйте и отладьте её. Попользуйтесь ею, чтобы убедиться, что она работает, как ожидалось. После этого добавляйте любые необходимые функции, повторяя цикл «Создание-Тестирование-Использование» столько раз, сколько потребуется. Помните, Программы выращиваются, а не строятся.
13.8 Резюме
Мы увидели, как создавать свои собственные программы/сценарии на Python, а также различные стадии написания программ. На данном этапе вам будет полезно создать соб- ственную программу по такому рецепту, как мы это делали в настоящей главе, чтобы лучше привыкнуть к Python, равно как и к решению задач.
Далее мы обсудим объектно-ориентированное программирование.
13.7. Процесс разработки программного обеспечения
107
Объектно-ориентированное
программирование
До сих пор наши программы состояли из функций, т.е. блоков выражений, которые мани- пулируют данными. Это называется процедурно-ориентированным стилем программиро- вания. Существует и другой способ организации программ: объединять данные и функ- ционал внутри некоего объекта. Это называется объектно-ориентированной парадигмой программирования. В большинстве случаев можно ограничиться процедурным програм- мированием, а при написании большой программы или если решение конкретной зада- чи того требует, можно переходить к техникам объектно-ориентированного программи- рования.
Два основных аспекта объектно-ориентированного программирования – классы и объ- екты. Класс создаёт новый тип, а объекты являются экземплярами класса. Аналогично,
когда мы говорим о «переменных типа int
», это означает, что переменные, которые хра- нят целочисленные значения, являются экземплярами (объектами) класса int
Замечание для программистов на статических языках
Обратите внимание, что даже целые числа рассматриваются как объекты (класса int
),
в отличие от C++ и Java (до версии 1.5), где целые числа являются примитивами. См.
help(int)
для более детального описания этого класса. Программисты на C# и Java 1.5
могут заметить сходство с концепцией упаковки и распаковки
1
Объекты могут хранить данные в обычных переменных, которые принадлежат объек- ту. Переменные, принадлежащие объекту или классу, называют полями. Объекты могут также обладать функционалом, т.е. иметь функции, принадлежащие классу. Такие функ- ции принято называть методами класса. Эта терминология важна, так как она помогает нам отличать независимые функции и переменные от тех, что принадлежат классу или объекту. Всё вместе (поля и методы) принято называть атрибутами класса.
Поля бывают двух типов: они могут принадлежать каждому отдельному экземпляру объ- екта класса или всему классу. Они называются переменными экземпляра и перемен-
ными класса соответственно.
1
boxing and unboxing
108
A Byte of Python (Russian), Версия 2.02
Класс создаётся ключевым словом class
. Поля и методы класса записываются в блоке кода с отступом.
14.1 self
Методы класса имеют одно отличие от обычных функций: они должны иметь дополни- тельно имя, добавляемое к началу списка параметров. Однако, при вызове метода никако- го значения этому параметру присваивать не нужно – его укажет Python. Эта переменная указывает на сам объект экземпляра класса, и по традиции она называется self
2
Хотя этому параметру можно дать любое имя, настоятельно рекомендуется использовать только имя self
; использование любого другого имени не приветствуется. Есть много до- стоинств использования стандартного имени: во-первых, любой человек, просматриваю- щий вашу программу, легко узнает его; во-вторых, некоторые специализированные Ин- тегрированные среды разработки (IDE) изначально рассчитаны на использование self
Замечание для программистов на C++, Java и C#
self в Python эквивалентно указателю this в C++ и ссылке this в Java и C#.
Вы, должно быть, удивляетесь, как Python присваивает значение self и почему вам не нужно указывать это значение самостоятельно. Поясним это на примере. Предположим,
у нас есть класс с именем
MyClass и экземпляр этого класса с именем myobject
. При вызове метода этого объекта, например, «
myobject.method(arg1, arg2)
», Python ав- томатически превращает это в «
MyClass.method(myobject, arg1, arg2)
» – в этом и состоит смысл self
Это также означает, что если какой-либо метод не принимает аргументов, у него всё равно будет один аргумент –
self
14.2 Классы
Простейший класс показан в следующем примере (сохраните как simplestclass.py
).
class
Person
:
pass
# Пустой блок
p
=
Person()
(p)
Вывод:
2
self – англ. «сам» (прим.перев.)
14.1. self
109
A Byte of Python (Russian), Версия 2.02
$ python3 simplestclass.py
<__main__.Person object at 0x019F85F0>
Как это работает:
Мы создаём новый класс при помощи оператора class и имени класса. За этим следует блок выражений, формирующих тело класса. В данном случае блок у нас пуст, на что указывает оператор pass
Далее мы создаём объект-экземпляр класса, записывая имя класса со скобка- ми. (Мы узнаем больше о
реализации
в следующем разделе). Для проверки мы выясняем тип переменной, просто выводя её на экран. Так мы видим, что у нас есть экземпляр класса
Person в модуле
__main__
Обратите внимание, что выводится также и адрес в памяти компьютера, где хранится ваш объект. На вашем компьютере адрес будет другим, так как
Python хранит объекты там, где имеется свободное место.
14.3 Методы объектов
Итак, мы выяснили что классы/объекты могут иметь методы, представляющие собой функции, за исключением дополнительной переменной self
. А теперь давайте рассмот- рим пример (сохраните как method.py
).
class
Person
:
def
sayHi
(
self
):
(
'Привет! Как дела?'
)
p
=
Person()
p sayHi()
# Этот короткий пример можно также записать как Person().sayHi()
Вывод:
$ python3 method.py
Привет! Как дела?
Как это работает:
Здесь мы видим self в действии. Обратите внимание, что метод sayHi не принимает параметров, но тем не менее, имеет self в определении функции.
14.3. Методы объектов
110
A Byte of Python (Russian), Версия 2.02 14.4 Метод
__init__
Существует много методов, играющих специальную роль в классах Python. Сейчас мы увидим значительность метода
__init__
Метод
__init__
запускается, как только объект класса реализуется. Этот метод полезен для осуществления разного рода инициализации, необходимой для данного объекта. Об- ратите внимание на двойные подчёркивания в начале и в конце имени.
Пример: (сохраните как oop_init.py
)
class
Person
:
def
__init__
(
self
, name):
self name
=
name
def
say_hi
(
self
):
(
'Привет! Меня зовут'
,
self name)
p
=
Person(
'Swaroop'
)
p say_hi()
# Предыдущие 2 строки можно
# Person('Swaroop').say_hi()
Вывод:
$ python oop_init.py
Привет! Меня зовут Swaroop
Как это работает:
Здесь мы определяем метод
__init__
так, чтобы он принимал параметр name
(наряду с обычным self
). Далее мы создаём новое поле с именем name
. Об- ратите внимание, что это две разные переменные, даже несмотря на то, что они обе названы name
. Это не проблема, так как точка в выражении self.
name обозначает, что существует нечто с именем «name», являющееся частью объекта «self», и другое name
– локальная переменная. Поскольку мы в явном виде указываем, к которому имени мы обращаемся, путаницы не возникнет.
Для создания нового экземпляра p
класса
Person мы указываем имя класса,
после которого – аргументы в скобках:
p = Person('Swaroop')
Метод
__init__
мы при этом не вызываем явным образом. В этом и заклю- чается специальная роль данного метода.
После этого мы получаем возможность использовать поле self.name в наших методах, что и продемонстрировано в методе say_hi
14.4. Метод
__init__
111
A Byte of Python (Russian), Версия 2.02 14.5 Переменные класса и объекта
Функциональную часть классов и объектов (т.е. методы) мы обсудили, теперь давайте ознакомимся с частью данных. Данные, т.е. поля, являются не чем иным, как обычны- ми переменными, заключёнными в пространствах имён классов и объектов. Это означа- ет, что их имена действительны только в контексте этих классов или объектов. Отсюда и название «пространство имён».
Существует два типа полей: переменные класса и переменные объекта, которые разли- чаются в зависимости от того, принадлежит ли переменная классу или объекту соответ- ственно.
Переменные класса разделяемы – доступ к ним могут получать все экземпляры этого клас- са. Переменная класса существует только одна, поэтому когда любой из объектов изме- няет переменную класса, это изменение отразится и во всех остальных экземплярах того же класса.
Переменные объекта принадлежат каждому отдельному экземпляру класса. В этом случае у каждого объекта есть своя собственная копия поля, т.е. не разделяемая и никоим образом не связанная с другими такими же полями в других экземплярах. Это легко понять на примере (сохраните как objvar.py
):
class
Robot
:
'''Представляет робота с именем.'''
# Переменная класса, содержащая количество роботов
population
=
0
def
__init__
(
self
, name):
'''Инициализация данных.'''
self name
=
name print
(
'(Инициализация
{0}
)'
format(
self name))
# При создании этой личности, робот добавляется
# к переменной 'population'
Robot population
+=
1
def
__del__
(
self
):
'''Я умираю.'''
(
'
{0}
уничтожается!'
format(
self name))
Robot population
-=
1
if
Robot population
==
0
:
(
'
{0}
был последним.'
format(
self name))
else
:
(
'Осталось
{0:d}
работающих роботов.'
format(
\
(продолжение на следующей странице)
14.5. Переменные класса и объекта
112
A Byte of Python (Russian), Версия 2.02
(продолжение с предыдущей страницы)
Robot population))
def
sayHi
(
self
):
'''Приветствие робота.
Да, они это могут.'''
(
'Приветствую! Мои хозяева называют меня
{0}
.'
format(
self name))
def
howMany
():
'''Выводит численность роботов.'''
(
'У нас
{0:d}
роботов.'
format(Robot population))
howMany
=
staticmethod
(howMany)
droid1
=
Robot(
'R2-D2'
)
droid1
sayHi()
Robot howMany()
droid2
=
Robot(
'C-3PO'
)
droid2
sayHi()
Robot howMany()
(
"
\nЗдесь роботы могут проделать какую-то работу.\n"
)
(
"Роботы закончили свою работу. Давайте уничтожим их."
)
del
droid1
del
droid2
Robot howMany()
Вывод:
$ python3 objvar.py
(Инициализация R2-D2)
Приветствую! Мои хозяева называют меня R2-D2.
У нас 1 роботов.
(Инициализация C-3PO)
Приветствую! Мои хозяева называют меня C-3PO.
У нас 2 роботов.
Здесь роботы могут проделать какую-то работу.
Роботы закончили свою работу. Давайте уничтожим их.
R2-D2 уничтожается!
Осталось 1 работающих роботов.
(продолжение на следующей странице)
14.5. Переменные класса и объекта
113
A Byte of Python (Russian), Версия 2.02
(продолжение с предыдущей страницы)
C-3PO уничтожается!
C-3PO был последним.
У нас 0 роботов.
Как это работает:
Это длинный пример, но он помогает продемонстрировать природу перемен- ных класса и объекта. Здесь population принадлежит классу
Robot
, и поэто- му является переменной класса. Переменная name принадлежит объекту (ей присваивается значение при помощи self
), и поэтому является переменной объекта.
Таким образом, мы обращаемся к переменной класса population как
Robot.
population
, а не self.population
. К переменной же объекта name во всех методах этого объекта мы обращаемся при помощи обозначения self.name
Помните об этой простой разнице между переменными класса и объекта. Так- же имейте в виду, что переменная объекта с тем же именем, что и переменная класса, сделает недоступной («спрячет») переменную класса!
Метод howMany принадлежит классу, а не объекту. Это означает, что мы мо- жем определить его как classmethod или staticmethod
, в зависимости от того, нужно ли нам знать, в каком классе мы находимся. Поскольку нам не нужна такая информация, мы воспользуемся staticmethod
Мы могли достичь того же самого, используя декораторы
:
@staticmethod
def
howMany
():
'''Выводит численность роботов.'''
(
'У нас
{0:d}
роботов.'
format(Robot population))
Декораторы можно считать неким упрощённым способом вызова явного оператора, как мы видели в этом примере.
Пронаблюдайте, как метод
__init__
используется для инициализации экземпляра
Robot с именем. В этом методе мы увеличиваем счётчик population на 1, так как добав- ляем ещё одного робота. Также заметьте, что значения self.name для каждого объекта свои, что указывает на природу переменных объекта.
Помните, что к переменным и методам самого объекта нужно обращаться, пользуясь
только
self
. Это называется доступом к атрибутам.
В этом примере мы также наблюдали применение строк документации для классов, рав- но как и для методов. Во время выполнения мы можем обращаться к строке документации класса при помощи «
Robot.__doc__
», а к строке документации метода – при помощи
«
Robot.sayHi.__doc__
».
Наряду с методом
__init__
, существует и другой специальный метод
__del__
, который
14.5. Переменные класса и объекта
114
A Byte of Python (Russian), Версия 2.02
вызывается тогда, когда объект собирается умереть, т.е. когда он больше не используется,
и занимаемая им память возвращается операционной системе для другого использова- ния. В этом методе мы просто уменьшаем счётчик
Robot.population на 1.
Метод
__del__
запускается лишь тогда, когда объект перестаёт использоваться, а поэто- му заранее неизвестно, когда именно этот момент наступит. Чтобы увидеть его в действии явно, придётся воспользоваться оператором del
, что мы и сделали выше.
1 ... 6 7 8 9 10 11 12 13 14