42

在 Python 2 中,我们可以重新分配TrueFalse(但不能None),但所有三个(True、、FalseNone)都被认为是内置变量。但是,在 Py3k 中,所有三个都根据文档更改为关键字。

根据我自己的猜测,我只能猜测是为了防止这种旧恶作剧的True, False = False, True恶作剧。然而,在 Python 2.7.5 中,也许在之前的版本中,诸如None = 3which reassigned之类的语句None引发了SyntaxError: cannot assign to None.

从语义上讲,我不相信True,FalseNone是关键字,因为它们最终是语义文字,这就是 Java 所做的。我检查了 PEP 0(索引),但找不到 PEP 来解释它们被更改的原因。

是否有性能优势或其他原因使它们成为关键字而不是文字或像Nonepython2 中的特殊情况?

4

3 回答 3

47

可能是因为 Python 2.6 不仅允许True = False而且还允许你说一些有趣的话,比如:

__builtin__.True = False

这将重置TrueFalse整个过程。它可能导致发生非常有趣的事情:

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

编辑:正如Mike所指出的,Python wiki还在Core Language Changes下声明了以下内容:

  • 制作 True 和 False 关键字。
    • 原因:不可能分配给他们。
于 2013-08-05T05:16:46.390 回答
11

主要有两个原因:

  1. 所以人们不会__builtin__.True = False在随机模块上进行恶作剧。(由 devnull 解释)
  2. 因为关键字比全局内置更快。在 Python 2.x 中,解释器在使用它们之前必须解析这些变量的值,这比关键字慢一些。(请参阅为什么 if True 比 if 1 慢?
于 2013-08-11T22:12:13.370 回答
3

这在几个月前在 python-dev 上讨论过。拥有大量指向 True 定义的链接会很烦人,这与指向例如 nonlocal 或 with statements doc 的链接相反。

我总结了为什么 True 和 False 会让事情“变得更好”。

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

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

    def True(): print True

  2. 让用户代码重新绑定内置名称 None、True 和 False 确实没有好的用例,使它们成为关键字几乎只有优点。

  3. 制作程序必须在每一步都在符号表中查找“True”才能找到 True 具有值 True 远非直观。(这就是为什么 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

参考:

开始与分配 True 和 False 相关的谈话:

一些辅助数据:

PS:一些数字显示True / 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
于 2013-08-15T07:29:30.447 回答