在Python中为True定义值时的奇怪行为
这不是一个实际问题——我只是对我观察到的一些奇怪的行为感到好奇,并想知道我是否正确理解“is”操作符 下面是一些可预测的Python解释器输出:在Python中为True定义值时的奇怪行为,python,boolean,boolean-expression,Python,Boolean,Boolean Expression,这不是一个实际问题——我只是对我观察到的一些奇怪的行为感到好奇,并想知道我是否正确理解“is”操作符 下面是一些可预测的Python解释器输出: >>> True is True True >>> (1==1) is True True 现在让我们定义一个名为True的变量: >>> True = 'abc' >>> True == 'abc' True >>> True is 'abc' True 对
>>> 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
有人能解释这种奇怪的行为吗?正如在这里经常发生的那样,我想我在打字的时候找到了答案
有两个“True”:一个是布尔值,另一个是名为True的变量;一开始,他们是平等的。这就是为什么像(1==1)这样的布尔运算即使在名为True的变量被更改时仍然可以返回True——它们返回的是布尔值True。但是它们并不等于“True”变量的新值,这是一个字符串。正在发生的是名称空间和交互式控制台隐藏它 最初,您有正常的
True
,它是\uuuuuuu内置的模块的一部分
当您重新定义True
时,实际上是在当前模块中定义它,在这种情况下,该模块只是默认的\uuuuuuu main\uuuuu
因此,实际上有两个不同的对象<代码>\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
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
要在您自己的答案中添加更多内容(应该是注释,但长度较长,需要格式化):
id
中的值(本质上)是Python中对象的内部标识,如果愿意,也可以称为“真实名称”。(从字面上看,它是一个C指针,变成了一个整数。)测试比较对象标识
>>> 1==1
True
>>> id(1==1)
7744528
这表明比较的布尔结果是“旧的”True
,该结果仍然可用作\uuuuu内置的.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
您重新绑定了名称\uuuuu main\uuuu.True
(解释器>>
提示符处的当前模块为\uuuuuuu main\uuuuu
):
以及:
当初学者编写类似以下函数时,Python程序中也经常发生这种情况:
def foo(list):
...
list
是一个内置函数,但在函数foo
中,名称已重新绑定到参数。然后在…
部分的某个地方,他们得到了一个惊喜:
x = list(y)
他们希望这个函数调用\uuuuu内置的.list
,但它尝试将其局部变量作为函数调用
(有可能,但通常不是很好的风格,导入并通过这些名称调用东西。也有可能重新绑定内置名称,但这是一个更糟糕的想法。:-)我喜欢这种情况@JMK是的,我想,伊玛是第一个回答这个问题的人:P我没有看到他的答案。True
基本上是1
,带有一种奇特的repr()
:-)True不是带有花哨的repr()
的1
。它是一个单例内置值,在条件中恰好计算为1。就解释器而言,使用不同的单例值也有这种行为,比如if省略号:print 3
,除了明显的模糊性使其在风格上异常之外,没有什么错。从省略号示例中可以看出(省略号在numpy数组中也有一个没有人使用的不同的切片函数),不能将单例的值看作是1
。例如,比较True+1
和省略号+1
isinstance(True,int)
奇怪的是True
不是保留关键字(或Python拥有的任何关键字)。@iamnotmaynard:True
已成为Python 3中的关键字,而且赋值将引发SyntaxError:assignment to keyword
。。。您可以将值重新分配给几乎所有的值。谢天谢地,它们通常是本地的,所以当一个粗心的程序员在他们的函数中这样做时,它会保持本地化状态。@CorleyBrigman:例如,id
是一个内置函数,但它经常被重新指定为对象属性(例如在Django ORM中)。我不确定它是否“不小心”,因为id()
builtin对于调试以外的任何事情都没有多大用处。作为对象属性,它是可以的-这不是C,您将始终以self.id
或object.id
(在命名空间中)的身份访问它。虽然我见过(甚至写过)像UID列表中id的这样的代码:
等等,但这很容易做到,这就解释了如何隐藏它。。。但是,如果您愿意,也可以执行\uuuuuu内置\uuuuu.True=4
。所以这并不能完全回答最初的问题。@CorleyBrigman:我在解释最初问题中代码中发生了什么。我只是说它比这个更深。。。您可以执行\uuuu内置
,并且1==1
仍将返回True。甚至在内置代码下面的东西都指向真实的对象,或者它是在python核心中处理的。
def foo(list):
...
x = list(y)