在Python/IPython解释器中为单个下划线_赋值

eol*_*dro 68 python interpreter function ipython read-eval-print-loop

我在Python 2.7中创建了这个函数ipython:

def _(v):
    return v
Run Code Online (Sandbox Code Playgroud)

以后,如果我打电话_(somevalue),我会_ = somevalue.

in[3]: _(3)
out[3]: 3
in[4]: print _
out[4]: 3
Run Code Online (Sandbox Code Playgroud)

功能消失了!如果我打电话给_(4)我:

TypeError: 'int' object is not callable`
Run Code Online (Sandbox Code Playgroud)

为什么?这个功能出了什么问题?

Mar*_*ers 105

Python解释器将最后一个表达式值赋给_.

此行为仅限于REPL解释器,旨在帮助进行交互式编码会话:

>>> import math
>>> math.pow(3.0, 5)
243.0
>>> result = _
>>> result
243.0
Run Code Online (Sandbox Code Playgroud)

标准 Python解释去一些长度上不虽然用户定义的值践踏; 如果你自己分配其他东西,_那么解释器就不会覆盖它(从技术上讲,_变量是一个__builtin__属性,你自己的赋值是'常规'全局变量).你没有使用标准的Python解释器; 你正在使用IPython,那个解释器并不那么谨慎.

IPython 明确记录了这种行为:

以下GLOBAL变量始终存在(因此不要覆盖它们!):

  • [_] (单个下划线):存储以前的输出,如Python的默认解释器.

[...]

在标准的Python REPL环境中,如果您分配了一些内容,_您仍然可以通过__builtins__._或删除_再次隐藏它的全局(del _)来访问最后一个表达式结果.

在Python解释器之外,按照_惯例用作可翻译文本函数的名称(参见gettext模块 ;外部工具查找该函数以提取可翻译的字符串).

并且,按照惯例,使用_作为赋值目标告诉读者您的代码将忽略该值; 例如[random.random() for _ in range(5)],生成5个随机浮点值的列表,或者foo, bar, _ = three_values不使用来自元组赋值的第3个值的信号.当_已经用于某个gettext功能时,__可以用于相同的目的.

  • @Stephan:在没有脚本的情况下打开python解释器,在REPL提示符下尝试.解释器编译语句并立即执行它们,这样可以很容易地快速尝试. (5认同)

Ash*_*ary 30

_是解释器中的特殊变量,它始终分配给前一个表达式的结果.所以,你不应该那样使用它.

BTW问题似乎与IPython shell有关,因为你的代码在普通的python shell中工作正常:

在普通的python shell中,当你为变量_赋值时,它只会被分配给那个对象,并且会失去它的特殊行为.


Python shell:

>>> 2*2
4
>>> _         #works as expected
4
>>> _ = 2     #after assignment, it's magic functionality is gone
>>> _*5       
10
>>> _
2
Run Code Online (Sandbox Code Playgroud)

IPython shell:

在IPython中的_行为与python shell的行为不同_; 即使你将它分配给某个变量,它也会在你做一些计算后立即更新.

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
Run Code Online (Sandbox Code Playgroud)

来自IPython的文档:

以下GLOBAL变量始终存在(因此不要覆盖它们!):

_ :(单个下划线):存储以前的输出,如Python的默认解释器...

从python 文档:

特殊标识符_在交互式解释器中用于存储上次评估的结果; 它存储在 __builtin__模块中.不处于交互模式时,_没有特殊含义且未定义.

注意:该名称_通常与国际化一起使用; 有关此约定的更多信息,请参阅gettext模块的文档.