为什么在Python 3中将True和False更改为关键字?

在Python 2中,我们可以重新分配TrueFalse (但不是None ),但是所有三个( TrueFalseNone )都被认为是内置variables。 然而,在Py3k中,所有这三个都按照文档更改为关键字。

从我自己的猜测来看,我只能猜测是为了防止这种来自旧的True, False = False, True恶作剧。 但是,在Python 2.7.5中,也许在之前,诸如None = 3语句被重新分配。 None引发SyntaxError: cannot assign to None

从语义上讲,我不相信TrueFalseNone是关键字,因为它们是Java的最后一个语义文字。 我检查了PEP 0(索引),我找不到PEP解释为什么他们改变了。

有没有性能优势或其他原因,使他们的关键字,而不是文字或特殊 – 他们像None Python在Python2?

可能是因为Python 2.6不仅允许True = False而且允许你说一些有趣的事情:

 __builtin__.True = False 

这将在整个过程中将True重置为False 。 这可能导致真正有趣的事情发生:

 >>> import __builtin__ >>> __builtin__.True = False >>> True False >>> False False >>> __builtin__.False = True >>> True False >>> False False 

编辑 :正如Mike指出的那样, Python维基在“ 核心语言变更”中也提到了以下内容:

  • 制作真假关键字。
    • 原因:使他们不可能的任务。

有两个原因,主要是:

  1. 所以人们不会做__builtin__.True = False恶作剧隐藏在一个随机模块上。 (如devnull解释)
  2. 因为关键字比全局内置的更快。 在Python 2.x中,解释器必须在使用它们之前parsing这些variables的值,这比关键字慢了一点。 (请参阅为什么如果True比1更慢? )

几个月前在python-dev上讨论过这个问题。 与True的定义有很多联系会很烦人,与例如nonlocal或with statements doc的链接相反。

而我的结论是为什么True和False会使事情“更加精细”。

  1. 重新绑定为循环内调用的函数的副作用。

    真正改变真的很容易,比如:

    def True(): print True

  2. 让用户代码重新绑定内置名称None,True和False,使关键字几乎只有加号,实际上没有好的用例。

  3. Make程序必须在符号表中查找每个步骤中的“True”,才能findTrue值真值远非直观。 (这就是为什么1比True更快)。

    x = compile('while 1:foop()','','exec')

    dis.dis(x)的

      0 SETUP_LOOP 19 (to 22) 3 JUMP_FORWARD 4 (to 10) 6 JUMP_IF_FALSE 11 (to 20) 9 POP_TOP >> 10 LOAD_NAME 0 (foop) 13 CALL_FUNCTION 0 16 POP_TOP 17 JUMP_ABSOLUTE 10 >> 20 POP_TOP 21 POP_BLOCK >> 22 LOAD_CONST 1 (None) 25 RETURN_VALUE 

x = compile('while True:foop()','','exec')

dis.dis(x)的

  0 SETUP_LOOP 19 (to 22) >> 3 LOAD_NAME 0 (True) 6 JUMP_IF_FALSE 11 (to 20) 9 POP_TOP 10 LOAD_NAME 1 (foop) 13 CALL_FUNCTION 0 16 POP_TOP 17 JUMP_ABSOLUTE 3 >> 20 POP_TOP 21 POP_BLOCK >> 22 LOAD_CONST 0 (None) 25 RETURN_VALUE 

参考:

开始谈话有关分配到真和假:

一些辅助数据:

PS:有些数字显示为真/ 1:

 [alex@lancelot test]$ timeit.py -c -s'import itertools as it' 'c=it.count()' 'while True:' ' if c.next()>99: break' 10000 loops, best of 3: 91 usec per loop [alex@lancelot test]$ timeit.py -c -s'import itertools as it' 'c=it.count()' 'while 1:' ' if c.next()>99: break' 10000 loops, best of 3: 76 usec per loop