Значение символа подчеркивания в Python

Предупреждение
Последний раз данная статья обновлялась 12.05.2022, информация может быть устаревшей.

Список вопросов к Python собеседованию

Наиболее простой и очевидный способ применения подчеркивания - это разделение слов в именах объектов:

  • lower_case_with_underscores
  • UPPER_CASE_WITH_UNDERSCORES
  • Capitalized_Words_With_Underscores (ugly!)1

Одинарные и двойные подчеркивания в именах переменных и методов имеют определенное значение. Часть вариантов использования - это просто договоренность и предназначены как подсказка программисту, а часть используется интерпретатором Python:2

  • _single_leading_underscore: слабый показатель того, что объект (переменная, функция, метод, класс) предназначен для «внутреннего использования» - protected на словах. (Например, from M import * не импортирует объекты, имена которых начинаются с подчеркивания);
  • single_trailing_underscore_: используется по соглашению, чтобы избежать конфликтов с ключевыми словами Python;
  • __double_leading_underscore: такие имена трансформируются в формат «имя класса + имя метода/атрибута». Это позволяет создавать уникальные методы и атрибуты классов (внутри класса FooBar __boo становится _FooBar__boo). Это также называется “Name Mangling” - интерпретатор меняет имя переменной таким образом, что затрудняет создание коллизий при расширении класса позже.;
  • __double_leading_and_trailing_underscore__: «магические» методы или атрибуты, которые живут в контролируемых пользователем пространствах имен. Например. __init__, __import__ или __file__. PEP 8 рекомендует никогда не придумывать таких имен, а использовать их только в соответствии с документацией.1

В интерпретаторе символ подчеркивания _ хранит результат последнего неошибочного действия, выведенного на экран, если он не был явно использован в качестве переменной.

Это связано с тем, что sys.stdout экранируется с помощью displayhook. Пример из официальной документации:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
def displayhook(value):
    if value is None:
        return
    # Set '_' to None to avoid recursion
    builtins._ = None
    text = repr(value)
    try:
        sys.stdout.write(text)
    except UnicodeEncodeError:
        bytes = text.encode(sys.stdout.encoding, 'backslashreplace')
        if hasattr(sys.stdout, 'buffer'):
            sys.stdout.buffer.write(bytes)
        else:
            text = bytes.decode(sys.stdout.encoding, 'strict')
            sys.stdout.write(text)
    sys.stdout.write("\n")
    builtins._ = value

Нижнее подчеркивание _ также используется для игнорирования ненужных нам значений.3

  • Игнорирование значения при распаковке
1
x, _, y = (3, 7, 8) # x = 3, y = 8
  • Игнорирование нескольких значений - “Extended Unpacking” Python 3.x
1
x, *_, y = (5, 7, 1, 8, 2) # x = 5, y = 2
  • Игнорирование индекса в цикле
1
2
for _ in range(100):
    do_something()
  • Игнорирование значения в определенной позиции
1
2
for _, val in some_dict.items():
    print(val)
Сокращения i18n и l10n
  • i18n - Internationalization: i(18 букв)n
  • l10n - Localization: l(10 букв)n
  • g11n - Globalization: g(11 букв)n
  • l12y - Localizability: l(12 букв)y

Пример использования из офф. документации4:

1
2
3
4
5
6
import gettext
gettext.bindtextdomain('myapplication','/path/to/my/language/directory')
gettext.textdomain('myapplication')
_ = gettext.gettext
# ...
print(_('This is a translatable string.'))

Это просто соглашение, а не синтаксис функции.

Этого соглашения придерживается и модуль gettext из встроенной стандартной библиотеки, и Django.

Символ нижнего подчеркивания может использоваться для разделения цифр в больших числах. Python 3.6

1
2
3
big_int = 2_000_000  # 2000000
hex_num = 0x_3212_ffff  # 840105983
bin_num = 0b_1010_0111  # 167