Assigning a value to single underscore _ in Python/IPython interpreter
I created this function in Python 2.7 with ipython
:
def _(v):
return v
later if I call _(somevalue)
, I get _ = somevalue
.
in[3]: _(3)
out[3]: 3
in[4]: print _
out[4]: 3
The function has disappeared! If I call _(4)
I get:
TypeError: 'int' object is not callable
Why? What's wrong with this function?
The Python interpreter assigns the last expression value to _
.
This behaviour is limited to the REPL interpreter only, and is intended to assist in interactive coding sessions:
>>> import math
>>> math.pow(3.0, 5)
243.0
>>> result = _
>>> result
243.0
The standard Python interpreter goes to some length to not trample on user-defined values though; if you yourself assign something else to _
then the interpreter will not overwrite that (technically speaking, the _
variable is a __builtin__
attribute, your own assignments are 'regular' globals). You are not using the standard Python interpreter though; you are using IPython, and that interpreter is not that careful.
IPython documents this behaviour explicitly:
The following GLOBAL variables always exist (so don’t overwrite them!):
[_]
(a single underscore) : stores previous output, like Python’s default interpreter.[...]
In the standard Python REPL environment, if you assigned something to _
you can still access the last expression result via __builtins__._
or by deleting the _
global that shadows it again (del _
).
Outside of the Python interpreter, _
is by convention used as the name of the translatable text function (see the gettext
module; external tools look for that function to extract translatable strings).
And, also by convention, using _
as an assignment target tells readers of your code that you are going to ignore that value; e.g. [random.random() for _ in range(5)]
to generate a list of 5 random float values, or foo, bar, _ = three_values
to signal a 3rd value from a tuple assignment will not be used. When _
is already used for a gettext
function, __
can be used for the same purposes.
_
is a special variable in interpreter, it is always assigned to the result of previous expression. So, you shoudn't use it like that.
BTW the problem seems to be related to IPython shell, because your code works fine in normal python shell:
In normal python shell when you assign anything to the variable _
then it'll remain assigned to that object only, and looses it special behaviour.
Python shell:
>>> 2*2
4
>>> _ #works as expected
4
>>> _ = 2 #after assignment, it's magic functionality is gone
>>> _*5
10
>>> _
2
IPython shell:
In IPython _
behaves differently than python shell's _
; even if you assign it to some variable then also it is going to be updated as soon as you do some calculation.
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
From IPython's docs:
The following GLOBAL variables always exist (so don’t overwrite them!):
_ : (a single underscore) : stores previous output, like Python’s default interpreter. ..
From python docs:
The special identifier
_
is used in the interactive interpreter to store the result of the last evaluation; it is stored in the__builtin__
module. When not in interactive mode,_
has no special meaning and is not defined.Note: The name
_
is often used in conjunction with internationalization; refer to the documentation for the gettext module for more information on this convention.