Присвоение значения одиночному подчеркиванию _ в интерпретаторе 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`
Почему? Что не так с этой функцией?
Ответы
Ответ 1
интерпретатор Python присваивает последнее значение выражения _
.
Это поведение ограничивается только REPL interpreter и предназначено для помощи в интерактивных сеансах кодирования:
>>> import math
>>> math.pow(3.0, 5)
243.0
>>> result = _
>>> result
243.0
Стандартный интерпретатор Python имеет длину, чтобы не попирать пользовательские значения; если вы сами присваиваете что-то еще _
, тогда интерпретатор не будет перезаписывать это (технически говоря, переменная _
является атрибутом __builtin__
, ваши собственные назначения являются "регулярными" глобалами). Однако вы не используете стандартный интерпретатор Python; вы используете IPython, и этот интерпретатор не так осторожен.
IPython явно описывает это поведение:
Следующие GLOBAL-переменные всегда существуют (поэтому не перезаписывайте их!):
-
[_]
(одно подчеркивание): сохраняет предыдущий вывод, например интерпретатор по умолчанию Pythons.
[...]
Вне интерпретатора Python _
по умолчанию используется как имя переводной текстовой функции (см. gettext
module; внешние инструменты ищут эту функцию для извлечения переводимых строк).
В циклах, используя _
в качестве цели назначения, читатели читают ваш код, что вы проигнорируете это значение; например [random.random() for _ in range(5)]
, чтобы сгенерировать список из 5 случайных значений float.
Ответ 2
_
- специальная переменная в интерпретаторе, она всегда назначается на результат предыдущего выражения. Таким образом, вы не будете так использовать.
Кстати, проблема, похоже, связана с оболочкой IPython, потому что ваш код отлично работает в обычной оболочке python:
В обычной оболочке python, когда вы присваиваете что-либо переменной _
, тогда она останется назначенной только этому объекту и теряет ее особый характер.
оболочка Python:
>>> 2*2
4
>>> _ #works as expected
4
>>> _ = 2 #after assignment, it magic functionality is gone
>>> _*5
10
>>> _
2
оболочка IPython:
В IPython _
ведет себя иначе, чем оболочка python _
; даже если вы присвоите его какой-либо переменной, тогда он также будет обновлен, как только вы выполните некоторые вычисления.
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 docs:
Всегда существуют следующие GLOBAL-переменные (поэтому не перезаписывать их):
_: (одно подчеркивание): сохраняет предыдущий вывод, например Pythons интерпретатор по умолчанию...
Из python docs:
Специальный идентификатор _
используется в интерактивном интерпретаторе для сохранить результат последней оценки; он хранится в __builtin__
. Если не в интерактивном режиме, _
не имеет специального значения и не определяется.
Примечание. Имя _
часто используется в сочетании с интернационализацией; обратитесь к документации для gettext модуль для получения дополнительной информации об этом соглашении.
Ответ 3
Если вы создаете переменную, назначенную "_", она маскируется/маскирует системную переменную _.