Какова цель единственной подчеркивания «_» в Python?

618

Что означает _после forв этом коде?

if tbh.bag:
   n = 0
   for _ in tbh.bag.atom_set():
      n += 1
alwbtc
источник
5
Для вашего случая было бы чище len(tbh.bag.atom_set())(если возвращаемое значение имеет __len__метод) илиsum(1 for _ in tbh.bag.atom_set())
Ник Т
В pylintдругой опции для фиктивных имен переменных есть префикс dummy_для имени переменной. Использование этого префикса с pylint, заставляет pylintне выдавать предупреждение. Также вы можете настроить шаблон фиктивной переменной для pylintразмещения таких вещей, как __.
Тревор Бойд Смит

Ответы:

781

_ имеет 4 основных традиционных использования в Python:

  1. Чтобы сохранить результат последнего выполненного выражения (/ оператор) в сеансе интерактивного интерпретатора. Этот прецедент был установлен стандартным интерпретатором CPython, и другие интерпретаторы последовали его примеру
  2. Для поиска перевода в i18n (см., Например, документацию gettext ), как в коде: raise forms.ValidationError(_("Please enter a correct username"))
  3. В качестве «одноразового» имени переменной общего назначения, указывающего, что часть результата функции намеренно игнорируется (Концептуально, она отбрасывается.), Как в коде: label, has_label, _ = text.partition(':') .
  4. Как часть определения функции (с использованием либо defили lambda), где сигнатура фиксируется (например, с помощью обратного вызова или API родительского класса), но этой конкретной реализации функции не нужны все параметры, как в коде, подобном следующему:callback = lambda _: True

(Долгое время в этом ответе перечислялись только первые три варианта использования, но четвертый случай встречался достаточно часто, как отмечалось здесь , чтобы его можно было явно перечислить)

Последний вариант использования «одноразовой переменной или имени параметра» может конфликтовать с вариантом использования поиска преобразования, поэтому необходимо избегать использования _в качестве одноразовой переменной в любом блоке кода, который также использует ее для перевода i18n (многие люди предпочитают двойное подчеркивание , __как их одноразовые переменные именно по этой причине).

ncoghlan
источник
19
Не могли бы вы объяснить, как это работает при вызове функции, например: поднять forms.ValidationError (_ («Пожалуйста, введите правильное имя пользователя»)) . Я видел это в коде Django, и не ясно, что происходит.
Джон C
41
Это использование 2 - по соглашению, _это имя, используемое для функции, которая выполняет поиск перевода интернационализации и локализации. Я почти уверен, что именно gettextбиблиотека C установила это соглашение.
ncoghlan
43
FWIW, я лично начал использовать __(двойное подчеркивание) в качестве моей одноразовой переменной общего назначения, чтобы избежать конфликта с любым из первых двух вариантов использования.
ncoghlan
14
Соглашения о новых сообществах, как правило, не имеют авторитетных источников - просто наблюдения за практиками, появившимися со временем. FWIW, я один из соавторов последних обновлений PEP 8, и мой ответ основан на 3 различных способах _использования имени переменной с тех пор, как я начал профессионально использовать Python в 2002 году.
ncoghlan
12
Соглашение в основном относится к распаковке кортежей: a, __, c = iterableнемедленно сообщает читателю, что мы распаковываем 3-кортеж, но только с использованием первого и последнего значений. Если мы вместо того, чтобы писать a, b, c = iterable, читатель (или автоматизированный код ЛИНТЕР) можно разумно ожидать , что все a, bи cбудет использоваться в дальнейшем (и если это не так , это может быть признаком ошибка где - то).
ncoghlan
207

Это просто имя переменной, и в Python принято использовать ее _для одноразовых переменных. Это просто указывает на то, что переменная цикла на самом деле не используется.

gsteff
источник
5
Вы имеете в виду, что он не представляет последнее возвращаемое значение?
alwbtc
31
@steve только в оболочке
Габи Пуркару
4
аналогично использованию _ в Прологе
Матиас
3
аналогично использованию ~ в Matlab
PatriceG
Обратите внимание, что в оболочке cpython, если вы явно укажете _, она перестает удерживать выходное значение предыдущего выражения. Это кажется ужасно непоследовательным, и стандарты языка Python должны учитывать это. Они должны просто определить _как одноразовое имя и не использовать его в качестве реального идентификатора.
theferrit32
78

Подчеркивание _рассматривается как переменная " Мне все равно " или " Throwaway " в Python

  • Интерпретатор python сохраняет последнее значение выражения в специальной переменной, которая называется _.

    >>> 10 
    10
    
    >>> _ 
    10
    
    >>> _ * 3 
    30
  • Подчеркивание _также используется для игнорирования определенных значений. Если вам не нужны конкретные значения или значения не используются, просто присвойте значения подчеркиванию.

    Игнорировать значение при распаковке

    x, _, y = (1, 2, 3)
    
    >>> x
    1
    
    >>> y 
    3

    Игнорировать индекс

    for _ in range(10):     
        do_something()
Ашиш Саху
источник
2
Есть третье использование, которое предназначено для функции интернационализации _("Hello world!").
Джефф Юнкер
3
На уровне процессора, есть ли на самом деле разница между «для _ в диапазоне» и «для х в диапазоне» и затем не использовать х? Или это только для удобства чтения?
iammax
1
@iammax Используя disмодуль, который я обнаружил, не было никакой разницы в байт-коде. Однако преимущества читабельности человека очевидны.
Алистер Карскэдден
21

Есть 5 случаев использования подчеркивания в Python.

  1. Для хранения значения последнего выражения в интерпретаторе.

  2. Для игнорирования конкретных значений. (так называемое «мне все равно»)

  3. Придавать особые значения и функции именам переменных или функций.

  4. Использовать как функции «Интернационализация (i18n)» или «Локализация (l10n)».

  5. Для разделения цифр номера нужно буквальное значение.

Вот хорошая статья с примерами от Mingrammer .

иметь значение
источник
2
На самом деле это довольно новый blog.pythonlibrary.org/2017/01/11/...
MichaelChirico
3

Что касается языков Python, _не имеет особого значения. Это действительный идентификатор так же , как _foo, foo_или _f_o_o_.

Любое специальное значение _чисто условно. Несколько случаев являются общими:

  • Пустое имя, когда переменная не предназначена для использования, но имя требуется синтаксисом / семантикой.

    # iteration disregarding content
    sum(1 for _ in some_iterable)
    # unpacking disregarding specific elements
    head, *_ = values
    # function disregarding its argument
    def callback(_): return True
  • Многие REPL / оболочки содержат результат последнего выражения верхнего уровня в builtins._.

    Специальный идентификатор _используется в интерактивном интерпретаторе для хранения результатов последней оценки; он хранится в builtinsмодуле. Когда не в интерактивном режиме, _не имеет особого значения и не определяется. [ источник ]

    Из-за способа поиска имен, если только они не скрываются глобальным или локальным _определением, на которое _ссылается голое builtins._.

    >>> 42
    42
    >>> f'the last answer is {_}'
    'the last answer is 42'
    >>> _
    'the last answer is 42'
    >>> _ = 4  # shadow ``builtins._`` with global ``_``
    >>> 23
    23
    >>> _
    4

    Примечание. Некоторые оболочки, например ipython, не относятся к builtins._специальному случаю _.

  • В контексте интернационализации и локализации _используется в качестве псевдонима для основной функции перевода.

    gettext.gettext (сообщение)

    Вернуть локализованный перевод сообщения, основываясь на текущем глобальном домене, языке и каталоге локали. Эта функция обычно называется псевдонимом _ () в локальном пространстве имен (см. Примеры ниже).

MisterMiyagi
источник