подсказка, которая должна сообщить другому программисту, что пере-
менная или метод, начинающиеся с одинарного символа подчеркивания,
предназначаются для внутреннего пользования. Эта договоренность
определена в PEP 8, руководстве по стилю оформления наиболее широко
применяемого исходного кода Python
1
.
Однако эта договоренность не обеспечивается интерпретатором Python.
В Python отсутствует строгое разграничение между «приватными» и «пу-
бличными» переменными, как в Java. Добавление одинарного символа
подчеркивания перед именем переменной больше похоже на размещение
крошечного подстрочного предупреждающего знака, который говорит:
«Послушай, эта переменная точно не предназначена быть частью от-
крытого интерфейса этого класса. Оставь-ка ее в покое».
1
См. PEP8: «Руководство по стилю оформления исходного кода Python»:
https://www .
python .org/dev/peps/pep-0008/
46 Глава 2 • Шаблоны для чистого Python
Взгляните на приведенный ниже пример:
class Test:
def __init__(self):
self.foo = 11
self._bar = 23
Что случится, если создать экземпляр этого класса и попробовать полу-
чить доступ к атрибутам
foo
и
_bar
, определенным в его конструкто-
ре
__init__
?
Давайте узнаем:
>>> t = Test() >>> t.foo
11
>>> t._bar
23
Как видите, одинарный начальный символ подчеркивания в
_bar
не поме-
шал нам «залезть» в класс и получить доступ к значению этой переменной.
Все потому, что в Python префикс, состоящий из одинарного подчерки-
вания, представляет собой просто согласованную договоренность — по
крайней мере в том, что касается имен переменных и методов. Вместе
с тем начальные символы подчеркивания влияют на то, как имена импор-
тируются из модулей. Предположим, что у вас есть модуль
my_module
и в
нем есть следующий фрагмент кода:
# my_module.py:
def external_func():
return 23
def _internal_func():
return 42
Так вот, если для импорта всех имен из модуля вы будете использовать
подстановочный импорт (wildcard import) (
*
), то Python не будет импор-
тировать имена с начальным символом подчеркивания (если только в мо-
дуле не определен список
__all__
, который отменяет такое поведение
1
):
1
См. документацию Python «Импортирование с подстановочным знаком * из пакета»:
https://docs .python .org/3/tutorial/modules .html#importing-from-a-package
2 .4 . Подчеркивания, дандеры и другое 47
>>> from my_module import *
>>> external_func()
23
>>> _internal_func() NameError: "name '_internal_func' is not defined"
К слову сказать, подстановочного импорта следует избегать, поскольку он
вносит неясность в то, какие имена присутствуют в пространстве имен
1
.
Ради ясности лучше придерживаться обычного импорта. Согласованные
правила именования с одинарным подчеркиванием, в отличие от подста-
новочного импорта, обычный импорт не затрагивает:
>>> import my_module
>>> my_module.external_func()
23
>>> my_module._internal_func()
42
Понимаю, этот момент может показаться немножко запутанным. Если
вы придерживаетесь рекомендаций PEP 8 в том, что подстановочного
импорта следует избегать, то все, что действительно необходимо запом-
нить, состоит в следующем:
Одинарные символы подчеркивания являются в Python согласованным
правилом именования, которое говорит о том, что то или иное имя пред-
назначается для внутреннего использования . Это договорное правило
обычно интерпретатором Python не обеспечивается и предназначено
для программиста только в качестве подсказки .
2 . Одинарный замыкающий символ
подчеркивания: var_
Иногда самое подходящее имя переменной уже занято ключевым словом
языка Python. По этой причине такие имена, как
class
или
def
, в Python
нельзя использовать в качестве имен переменных. В этом случае можно
в конец имени добавить символ одинарного подчеркивания, чтобы из-
бежать конфликта из-за совпадения имен:
1
См. PEP 8 «Импортирование»:
http://pep8 .org/#imports
48 Глава 2 • Шаблоны для чистого Python
>>> def make_object(name, class):
Do'stlaringiz bilan baham: |