这不是一个实际问题 - 我只是对我观察到的一些奇怪行为感到好奇,并且想知道我是否正确理解了“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
任何人都可以解释这种奇怪的行为吗?
答案 0 :(得分:6)
正如在这里经常发生的那样,我想我在输入问题时想出了答案。
有两个“真”:一个是布尔值,另一个是名为True的变量;最初,他们彼此相等。这就是为什么布局操作如(1 == 1)仍然可以返回True,即使已经改变了名为True的变量 - 它们返回布尔值True。然而,它们不等于“True”变量的新值,它是一个字符串。
答案 1 :(得分:5)
正在发生的是命名空间和交互式控制台隐藏它。
最初,您有正常的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
答案 2 :(得分:2)
要为自己的答案添加更多内容(应该是评论,但是,很长,需要格式化):
python2.7
...
>>> import __builtin__
>>> id(True)
7744528
>>> id(__builtin__.True)
7744528
>>> True = 'abc'
>>> id(True)
34386540544
来自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
是一个内置函数,但在函数foo
内,名称已重新绑定到参数。然后在...
部分的某个地方,他们会感到惊讶:
x = list(y)
他们希望这会调用__builtin__.list
,但它会尝试将其局部变量作为函数调用。
(import __builtin__
可能,但通常不是好的风格,而是通过这些名称来调用。还可以重新绑定__builtin__
名称,但这是一个更糟糕的想法。: - ))