it-swarm.com.ru

Присвоение значения одиночному подчеркиванию _ в интерпретаторе Python / IPython

Я создал эту функцию в Python 2.7 с ipython:

def _(v):
    return v

позже, если я позвоню _(somevalue), я получу _ = somevalue.

in[3]: _(3)
out[3]: 3
in[4]: print _
out[4]: 3

Функция исчезла! Если я позвоню _(4), я получу:

TypeError: 'int' object is not callable`

Зачем? Что не так с этой функцией?

68
eolandro

Интерпретатор Python назначает последнее значение выражения для _.

Это поведение ограничено только интерпретатор REPL и предназначено для помощи в интерактивных сеансах кодирования:

>>> import math
>>> math.pow(3.0, 5)
243.0
>>> result = _
>>> result
243.0

Интерпретатор Python делает все возможное, чтобы не растоптать пользовательские значения; если вы сами назначите что-то else для _, то интерпретатор не перезапишет это (технически говоря, переменная _ является атрибутом __builtin__ =, ваши собственные задания - это "обычные" глобалы). Вы не используете стандартный интерпретатор Python; вы используете IPython, и этот интерпретатор не так осторожен.

IPython документально описывает это поведение :

Следующие глобальные переменные всегда существуют (поэтому не перезаписывайте их!):

  • [_] (одиночное подчеркивание): сохраняет предыдущий вывод, как интерпретатор Python по умолчанию.

[...]

В стандартной среде Python REPL, если вы присвоили что-то _, вы все равно можете получить доступ к последнему результату выражения через __builtins__._ или удалив глобальный _, который затемняет его (del _).

За пределами интерпретатора Python _ по умолчанию используется в качестве имени переводимой текстовой функции (см. модуль gettext ; внешние инструменты ищут эту функцию для извлечения переводимых строк).

И, также по соглашению, использование _ в качестве цели назначения сообщает читателям вашего кода, что вы собираетесь игнорировать это значение; например [random.random() for _ in range(5)] для генерации списка из 5 случайных значений с плавающей запятой или foo, bar, _ = three_values для сигнализации о 3-м значении из назначения Tuple не будут использоваться. Когда _ уже используется для функции gettext, __ может использоваться для тех же целей.

105
Martijn Pieters

_ - это специальная переменная в интерпретаторе, она всегда присваивается результату предыдущего выражения. Таким образом, вы не должны использовать это так.

Кстати, проблема, похоже, связана с IPython Shell, потому что ваш код работает нормально в обычной python Shell:

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


Оболочка Python:

>>> 2*2
4
>>> _         #works as expected
4
>>> _ = 2     #after assignment, it's magic functionality is gone
>>> _*5       
10
>>> _
2

Оболочка IPython :

В IPython _ ведет себя иначе, чем python Shell's _; даже если вы назначите его какой-либо переменной, он также будет обновлен, как только вы выполните некоторые вычисления.

In [1]: 2*2
Out[1]: 4

In [2]: _
Out[2]: 4

In [3]: _ = 10

In [4]: _*10
Out[4]: 100

In [5]: _
Out[5]: 100

Из IPython's документы :

Следующие глобальные переменные всегда существуют (поэтому не перезаписывайте их!):

_: (единственное подчеркивание): сохраняет предыдущий вывод, как интерпретатор Python по умолчанию. ..

От python документы :

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

Примечание : имя _ часто используется в сочетании с интернационализацией; обратитесь к документации для модуля gettext для получения дополнительной информации об этом соглашении.

30
Ashwini Chaudhary