8

这不是一个实际问题——我只是对我观察到的一些奇怪行为感到好奇,想知道我是否正确理解了“is”运算符。

这是一些可预测的 Python 解释器输出:

>>> True is True
True
>>> (1==1) is True
True

现在让我们定义一个名为 True 的变量:

>>> True = 'abc'
>>> True == 'abc'
True
>>> True is 'abc'
True

对于布尔运算,解释器仍将返回“True”,但布尔运算的结果被认为既不等于“abc”也不等于 True。

>>> (1==1)
True
>>> (1==1) is 'abc'
False
>>> (1==1) is True
False

谁能解释这种奇怪的行为?

4

3 回答 3

6

就像这里经常发生的那样,我想我在输入问题时想出了答案。

“True”有两个:一个是布尔值,另一个是名为True的变量;最初,它们彼此相等。这就是为什么像 (1==1) 这样的布尔运算即使在名为 True 的变量已更改时仍然可以返回 True - 它们返回布尔值 True。然而它们不等于“True”变量的新值,它是一个字符串。

于 2013-10-28T15:54:06.460 回答
5

正在发生的是命名空间和隐藏它的交互式控制台。

最初你有 normal True,它是__builtin__模块的一部分。

当您重新定义时True,您实际上是在当前模块中定义它,在这种情况下,它只是默认的一个__main__

因此,您实际上有两个不同的对象。__builtin__.True__main__.True

In [1]: import __builtin__, __main__

In [2]: True = "a bad idea"

In [3]: __main__.True
Out[3]: 'a bad idea'

In [4]: __builtin__.True
Out[4]: True
于 2013-10-28T16:06:34.760 回答
2

要为您自己的答案添加更多内容(应该是评论,但是很长并且需要格式化):

python2.7
...
>>> import __builtin__
>>> id(True)
7744528
>>> id(__builtin__.True)
7744528
>>> True = 'abc'
>>> id(True)
34386540544

from 的值id(本质上)是 Python 中对象的内部标识,或者如果您愿意,也可以是“真名”。(它实际上是一个转换为整数的 C 指针。)is测试比较对象身份。

>>> 1==1
True
>>> id(1==1)
7744528

这表明比较的布尔结果是“旧的” True,仍然可以作为__builtin__.True.

您重新绑定了名称(您在解释器提示下__main__.True的当前模块是):>>>__main__

>>> True
'abc'
>>> __builtin__.True
True

和:

>>> import __main__
>>> id(__main__.True)
34386540544
>>> __main__.True
'abc'
>>> 

同样的事情经常发生在初学者的 Python 程序中,当他们编写如下函数时:

def foo(list):
    ...

list是一个内置函数,但在 function 内部foo,名称已重新绑定到参数。然后在该...部分的某个地方,他们得到了一个惊喜:

    x = list(y)

他们希望 this 调用__builtin__.list,但它尝试将其局部变量作为函数调用。

(有可能,但通常不是很好的风格,import __builtin__而是通过这些名称来调用事物。也可以重新绑定__builtin__名称,但这是一个更糟糕的主意。:-))

于 2013-10-28T16:07:41.637 回答