Имена в классе с начальным подчеркиванием просто указывают другим программистам, что атрибут или метод предназначены для частного использования. Однако с самим названием ничего особенного не делается.
Цитата PEP-8 :
_single_leading_underscore: слабый индикатор «внутреннего использования». Например,
from M import *
не импортирует объекты, имена которых начинаются с подчеркивания.
Из документы Python :
Любой идентификатор формы
__ spam
(не менее двух ведущих подчеркиваний, не более одного подчеркивания в конце) текстуально заменяется на_classname__spam
, гдеимя класса
- это имя текущего класса с подчеркивание (и) удалено. Это изменение выполняется без учета синтаксической позиции идентификатора, поэтому его можно использовать для определения частных экземпляров и переменных класса, методов, переменных, хранящихся в глобальных объектах, и даже переменных, хранящихся в экземплярах. закрытый для этого класса в экземплярах других классов.
И предупреждение с той же страницы:
Изменение имен предназначено для того, чтобы дать классам простой способ определять «частные» переменные и методы экземпляра, не беспокоясь о переменных экземпляра, определенных производными классами, или сбрасывании с экземпляром переменные по коду вне класса. Обратите внимание, что правила искажения разработаны в основном для предотвращения несчастных случаев; определенная душа по-прежнему может получить доступ или изменить переменную, которая считается частной.
>>> class MyClass():
... def __init__(self):
... self.__superprivate = "Hello"
... self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}
Пока отличные ответы, но некоторые лакомые кусочки отсутствуют. Одиночное подчеркивание в начале - не совсем просто соглашение: если вы используете из импорта foobar *
, а модуль foobar
не определяет __ all __
, имена, импортированные из модуля , не включают имена с начальным подчеркиванием. Допустим, это в основном соглашение, так как этот случай - довольно неясный угол; -).
Соглашение о начальном подчеркивании широко используется не только для частных имен, но также для чего C ++ будет называть защищенными - например, имена методов, которые полностью предназначены для переопределения подклассами (даже те, которые имеют , которые должны быть переопределены, поскольку в базовом классе они вызывают NotImplementedError
! -), часто встречаются с одним ведущим подчеркиванием имена для указания коду с использованием экземпляров этого класса (или подклассов), которые не предназначены для прямого вызова указанных методов.
Например, чтобы создать потокобезопасную очередь с другой дисциплиной организации очереди, чем FIFO, импортирует Queue, подклассы Queue.Queue и переопределяет такие методы, как _get
и _put
; "клиентский код" никогда не вызывает эти ("ловушки") методы, а скорее ("организующий" ) общедоступные методы, такие как put
и get
(это известно как шаблон проектирования Template Method - см., например, здесь , чтобы узнать об интересном презентация, основанная на видео моего выступления на эту тему, с добавлением резюме стенограммы).
Правка: ссылки на видео в описании переговоров теперь не работают. Вы можете найти первые два видео здесь и здесь .
__ foo __
: это просто соглашение, способ для системы Python использовать имена, которые не будут конфликтовать с именами пользователей.
_foo
: это просто соглашение, способ для программиста указать, что переменная является частной (что бы это ни значило в Python).
__ foo
: это имеет реальное значение: интерпретатор заменяет это имя на _classname__foo
как способ гарантировать, что имя не будет перекрываться с аналогичным именем в другом классе.
Никакая другая форма подчеркивания не имеет значения в мире Python.
В этих соглашениях нет разницы между классом, переменной, глобальным и т. д. .
Одинарное начало подчеркивание - это соглашение. нет никакой разницы с точки зрения интерпретатора, начинаются ли имена с одного символа подчеркивания или нет.
Двойные подчеркивания в начале и в конце используются для встроенных методов, таких как __ init __
, __ bool __
и т. Д.
Двойные подчеркивания в начале и в конце являются условными тоже, однако, методы класса будут искажены интерпретатором. Для переменных или имен базовых функций разницы нет.
Хороший вопрос, дело не только в методах. Функции и объекты в модулях обычно также имеют префикс с одним подчеркиванием и могут иметь префикс двух.
Но имена __double_underscore, например, не изменяются в модулях. Случается, что имена, начинающиеся с одного (или нескольких) символов подчеркивания, не импортируются, если вы импортируете все из модуля (из модуля import *), а также имена не отображаются в справке (модуль).
Accroding к https://dbader.org/blog/meaning-of-underscores-in-python