【问题标题】:Why were True and False changed to keywords in Python 3为什么 True 和 False 在 Python 3 中改为关键字
【发布时间】:2013-08-05 17:26:04
【问题描述】:

在 Python 2 中,我们可以重新分配 TrueFalse(但不是 None),但所有三个(TrueFalseNone)都被视为内置变量。但是,在 Py3k 中,这三个都被更改为 the docs 的关键字。

根据我自己的猜测,我只能猜测这是为了防止像 this 这样源自旧的 True, False = False, True 恶作剧的恶作剧。然而,在 Python 2.7.5 中,或许在之前的版本中,像 None = 3 这样重新分配了 None 的语句引发了 SyntaxError: cannot assign to None

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

将它们设为关键字而不是文字或像 python2 中的 None 那样特殊封装它们是否有性能优势或其他原因?

【问题讨论】:

    标签: python keyword


    【解决方案1】:

    可能是因为 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 wiki 还在核心语言更改下声明了以下内容:

    • 创建 True 和 False 关键字。
      • 原因:无法分配给他们。

    【讨论】:

    • 如果TrueFalseNone 而不是关键字,这样的恶作剧不会停止吗? >>> __builtin__.None = 5 SyntaxError: cannot assign to None
    • 从 2.6 开始对None 进行部分限制。
    • 他们不希望TrueFalse 成为保留字时,似乎有一个time,但显然它改变了:)
    • @SnakesandCoffee 使 None 成为常量的举动是暂时的。见mail.python.org/pipermail/python-dev/2004-July/046294.html
    • @Mehrdad:即使您尝试setattr(builtins, 'False', True),表达式False 也不会查找builtins.False 的值。 False 关键字直接引用 False 对象,而不是内置模块中的属性值。
    【解决方案2】:

    主要有两个原因:

    1. 所以人们不会在随机模块上隐藏__builtin__.True = False 恶作剧。 (由 devnull 解释)
    2. 因为关键字比全局内置命令更快。在 Python 2.x 中,解释器在使用它们之前必须解析这些变量的值,这比关键字慢一点。 (见Why is if True slower than if 1?

    【讨论】:

      【解决方案3】:

      这是几个月前在 python-dev 上讨论过的。 拥有大量指向 True 定义的链接会很烦人,这与指向例如的链接相反。非本地或 with 语句文档。

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

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

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

        def True(): print True

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

      3. Make 程序必须在每一步都在符号表中查找“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
      

      参考:

      开始与分配真假相关的谈话:

      一些辅助数据:

      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
      

      【讨论】:

        猜你喜欢
        • 2015-09-30
        • 2014-06-04
        • 2023-03-31
        • 2019-04-24
        • 2012-07-06
        • 2023-02-23
        • 2015-10-03
        相关资源
        最近更新 更多