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

69

我在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

为什么?这个函数有什么问题吗?


10
不,这不是那个问题的重复。我在我的回答中提到了下划线函数的用法,但这不是OP所问的。这是关于为什么Python交互式解释器将其他内容赋给“_”。 - Martijn Pieters
2
你是对的,我在发布可能重复的内容后意识到了这一点。由于我们无法撤回投票关闭,请参考(人们肯定会通过此页面寻找链接问题的答案),我认为保留引用更具信息性,而不是删除评论。 - dimo414
3个回答

106
Python解释器将最后一个表达式的值赋给_
这种行为仅适用于REPL interpreter,旨在帮助交互式编程会话。
>>> import math
>>> math.pow(3.0, 5)
243.0
>>> result = _
>>> result
243.0

标准的Python解释器会尽力避免覆盖用户定义的值,如果你自己将其他内容分配给_,那么解释器不会覆盖它(严格来说,_变量是一个__builtin__属性,你自己的分配是“常规”的全局变量)。但你并没有使用标准的Python解释器;你正在使用IPython,而该解释器并不那么小心。

IPython 明确记录了这种行为

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

  • [_](一个下划线):存储以前的输出,就像Python的默认解释器一样。

[...]

在标准的Python REPL环境中,如果你把某些东西赋值给_,你仍然可以通过__builtins__._来访问最后一个表达式的结果,或者通过删除遮盖它的_全局变量(del _)来访问它。
在Python解释器之外,按照惯例,_被用作可翻译文本函数的名称(请参见gettext模块;外部工具会查找该函数以提取可翻译字符串)。
同样按照惯例,将_用作赋值目标告诉代码读者您将忽略该值;例如,使用[random.random() for _ in range(5)]生成一个包含5个随机浮点数值的列表,或者使用foo, bar, _ = three_values表示元组赋值的第三个值将不会被使用。当_已经用于gettext函数时,可以使用__来实现相同的目的。

交互式编程会话是什么?类似于一种指导性的东西吗? - Stephan
5
在没有脚本的情况下打开Python解释器,在REPL提示符处尝试一些操作。解释器会编译语句并立即执行它们,这样可以很方便地快速尝试某些东西。 - Martijn Pieters

31

_是解释器中的一个特殊变量,它总是被赋值为前一个表达式的结果。因此,你不应该像那样使用它。

顺便说一句,这个问题似乎与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

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

来自IPython的文档:

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

_:(一个下划线):存储先前的输出,就像Python的默认解释器一样。 ..

来自Python的文档:

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

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


虽然我没有安装IPython,但我可以确认这是正常的(官方CPython?)交互式shell的行为(在2.7.2版本中)。 - 2rs2ts

-1

如果你创建一个赋值给“_”的变量,它会掩盖系统变量“_”。


2
那个系统变量 _ 是什么? - Martijn Pieters
同样的问题,我也不知道如何解决。 - Ahmed C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接