为何给True/False赋值不如我预期的那样?
在回答另一个问题的时候,我写了以下代码,乍一看它的表现似乎很奇怪:
print True # outputs true
True = False; print True # outputs false
True = True; print True # outputs false
True = not True; print True # outputs true
有没有人能解释一下这个奇怪的行为?我觉得这可能和Python的对象模型有关,但我不太确定。
这是在Cygwin下的2.5.2版本。
5 个回答
在2.x版本中,True和False并不是关键字,所以你可以用其他名字来覆盖它们。
想象一下这样的情况:
A = True
B = False
print A # true
A = B; print A # false
A = A; print A # false, because A is still false from before
A = not A; print A # true, because A was false, so not A is true
其实这里发生的事情是一样的,但在你的版本中让人感到困惑,因为你没有想到你可以重新定义真(True)和假(False)。
Python有这两个内置对象(还有其他的)。它们其实就是对象;一开始,它们还没有名字,但为了方便理解,我们就叫它们 0x600D
和 0xBAD
。
在执行一个Python(2.x)脚本之前,名字 True
被绑定到对象 0x600D
,而名字 False
被绑定到对象 0xBAD
。所以当程序提到 True
时,它实际上是在看 0x600D
。
因为 0x600D
和 0xBAD
知道它们通常是通过名字 True
和 False
来使用的,所以当它们被打印出来时,就会显示这些名字,也就是说 0x600D
的 __str__
方法返回 'True'
,以此类推。
True = False
现在把名字 True
绑定到一个不同的对象上。从现在开始,名字 True
和 False
都指向同一个对象 0xBAD
,当打印时,它会输出 False
。
True = True
实际上并没有做什么:它只是把名字 True
绑定到这个对象上(无论是新名字还是旧名字)。由于(因为前一步)True
在这之前指向 0xBAD
,所以在这之后它仍然指向 0xBAD
。因此,打印时仍然输出 False
。
True = not True
首先获取名字 True
绑定的对象,也就是 0xBAD
。然后把这个对象交给 not
操作符。not
不关心(也不知道)这里用什么名字来指代 0xBAD
,它只知道当给它 0xBAD
时,它应该返回 0x600D
。这个返回值接着被赋值给赋值操作符 =
,将名字 True
绑定到这个对象上。
因为现在名字 True
又一次指向对象 0x600D
,所以调用 print True
时会输出 True
,一切又恢复正常了。