为何给True/False赋值不如我预期的那样?

34 投票
5 回答
14974 浏览
提问于 2025-04-15 17:58

在回答另一个问题的时候,我写了以下代码,乍一看它的表现似乎很奇怪:

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 个回答

18

在2.x版本中,True和False并不是关键字,所以你可以用其他名字来覆盖它们。

45

想象一下这样的情况:

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)。

78

Python有这两个内置对象(还有其他的)。它们其实就是对象;一开始,它们还没有名字,但为了方便理解,我们就叫它们 0x600D0xBAD

在执行一个Python(2.x)脚本之前,名字 True 被绑定到对象 0x600D,而名字 False 被绑定到对象 0xBAD。所以当程序提到 True 时,它实际上是在看 0x600D

因为 0x600D0xBAD 知道它们通常是通过名字 TrueFalse 来使用的,所以当它们被打印出来时,就会显示这些名字,也就是说 0x600D__str__ 方法返回 'True',以此类推。

True = False

现在把名字 True 绑定到一个不同的对象上。从现在开始,名字 TrueFalse 都指向同一个对象 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,一切又恢复正常了。

撰写回答