Символ нижнего подчеркивания
Символу нижнего подчеркивания (_) в Python присущ ряд особенностей.
В большинстве языков программирования (хотя, конечно же не во всех) этот символ используется в названиях функций и переменных, но в Python он имеет особое значение. Если вы Python-программист, то вероятно знакомы с таким синтаксисом: for _ in range(10)
, __init__(self)
.
Этот пост посвящен объяснению того, как использовать нижнее подчеркивание (_) и как его понимать в различных контекстах.
Известно пять случаев с использования нижнего подчеркивания в Python.
- Для хранения значения последнего выражения в интерпретаторе.
- Для игнорирования конкретного значения (так сказать «Мне без разницы»).
- Для придания специального значения переменным и функциям при наименовании.
- Для использования функций «Internationalization(i18n)» или «Localization(l10n)».
- Для разделения цифр в числе или символов в литерале.
Давайте посмотрим каждый из перечисленных случаев.
Случай использования в интерпретаторе
Интерпретатор Python’а хранит последнее значение в специальной переменной с именем «_». Эта особенность используется в первую очередь в стандартном интерпретаторе CPython, как, впрочем, и в других интерпретаторах Python.
>>> 10 10 >>> _ 10 >>> _ * 3 30 >>> _ * 20 600
Случай игнорирования значений
Нижнее подчеркивание также используется для игнорирования конкретных значений. Если конкретное значение не нужно или значения нигде не используются, просто присвойте их нижнему подчеркиванию.
# Ignore a value when unpacking x, _, y = (1, 2, 3) # x = 1, y = 3 # Ignore the multiple values. It is called "Extended Unpacking" which is available in only Python 3.x x, *_, y = (1, 2, 3, 4, 5) # x = 1, y = 5 # Ignore the index for _ in range(10): do_something() # Ignore a value of specific location for _, val in list_of_tuple: do_something()
Случай придания специфических значений именам переменных и функций
Нижнее подчеркивание часто используется в наименованиях. Стиль кодирования PEP8 в языке Python вводит соглашения по использованию следующих случаев наименований.
_single_leading_underscore
Это соглашение используется для объявления приватных переменных, функций, методов и классов в модуле. При этом все, что связано с этим соглашением, игнорируется в from module import *
.
Хотя, конечно же, Python не поддерживает истинной приватности, поэтому можно непосредственно вызывать их из других модулей. Поэтому иногда это называют «нестрогий указатель внутреннего использования«.
_internal_name = 'one_nodule' # private variable _internal_version = '1.0' # private variable class _Base: # private class _hidden_factor = 2 # private variable def __init__(self, price): self._price = price def _double_price(self): # private method return self._price * self._hidden_factor def get_double_price(self): return self._double_price()
single_trailing_underscore_
Это соглашение предотвращает конфликты между ключевыми или стандартными словами.
Tkinter.Toplevel(master, class_='ClassName') # Avoid conflict with 'class' keyword list_ = List.objects.get(1) # Avoid conflict with 'list' built-in type
__double_leading_underscore
В этом случае речь идет о синтаксисе, а не о соглашении. Двойное нижнее подчеркивание искажает имена атрибутов класса и исключает конфликты между именами атрибутов классов. (Так называемое «декорирование», означающее, что компилятор или интерпретатор изменяет имена переменных или функций по некоторым правилам). Правило декорирования в Python добавляется «_ИмяКласса» перед именами атрибутов, объявленных с двойным нижним подчеркиванием.
То есть, если написать метод с именем «__метод» в классе, имя будет декорировано следующим образом: «_ИмяКласса__метод».
class A: def _single_method(self): pass def __double_method(self): # for mangling pass class B(A): def __double_method(self): # for mangling pass
Так как именованные атрибуты с двойным нижним подчеркиванием будут декорированы, так показано выше, мы не сможем получить к ним доступ по «ИмяКласса.__метод». Некоторые иногда пользуются этим как свойством подлинного сокрытия, на самом же деле это не служит для сокрытия и не рекомендуется для применения с подобными целями. Подробную информацию по этой теме можно найти в разделе по наименованиям в Python.
__double_leading_and_trailing_underscore__
Это соглашение используется для специальных переменных или методов (так называемый «магический метод») таких как __init__
, __len__
. Эти методы определяют особые синтаксические признаки или выполняют специфические действия. Например, __file__
указывает местоположение Python-файла, __eq__
выполняется, когда истинно условие a == b
.
Конечно можно создать специальный пользовательский метод, однако чаще прибегают к модификации предопределенных методов. (Например, для инициализации с помощью __init__
класса, который будет использоваться при создании экземпляра класса.)
class A: def __init__(self, a): # use special method '__init__' for initializing self.a = a def __custom__(self): # custom special method. you might almost do not use it pass
Случай использования функций Internationalization(i18n) или «Localization(l10n)
Это просто соглашение, без синтаксических функций. Нижнее подчеркивание не означает i18n/l10n, это только соглашение, связывающее i18n / l10n, с переменной нижнего подчеркивания, взятой из соглашения в языке программирования С.
Встроенная библиотека gettext
, а также фреймворк Django также поддерживают и используют это соглашение.
# see official docs : https://docs.python.org/3/library/gettext.html import gettext gettext.bindtextdomain('myapplication','/path/to/my/language/directory') gettext.textdomain('myapplication') _ = gettext.gettext # ... print(_('This is a translatable string.'))
Случай разделения чисел в числе или символов в литерале
Это свойство было добавлено в Python 3.6 и используется для разделения чисел или цифр с помощью нижнего подчеркивания для их удобочитаемости.
dec_base = 1_000_000 bin_base = 0b_1111_0000 hex_base = 0x_1234_abcd print(dec_base) # 1000000 print(bin_base) # 240 print(hex_base) # 305441741
Заключение
Итак, мы рассмотрели особенности и назначения применения нижнего подчеркивания в Python. И хотя я Python-программист, я сам не знал о некоторых его свойствах до написания этого поста. В частности, совершенно новым для меня оказалось использование функций i18n/l10n.
Надеюсь, что вы, как и я, нашли для себя много полезного при чтении моего поста. Спасибо!
Перевод статьи mingrammer: Understanding the underscore( _ ) of Python