为什么Python 3允许"00"作为0的文字而不允许"01"作为1的文字?

wal*_*rus 109 python integer literals python-3.x leading-zero

为什么Python 3允许"00"作为0的文字而不允许"01"作为1的文字?有充分的理由吗?这种不一致令我感到困惑.(我们正在讨论Python 3,它故意破坏向后兼容性以实现一致性等目标.)

例如:

>>> from datetime import time
>>> time(16, 00)
datetime.time(16, 0)
>>> time(16, 01)
  File "<stdin>", line 1
    time(16, 01)
              ^
SyntaxError: invalid token
>>>
Run Code Online (Sandbox Code Playgroud)

nne*_*neo 101

根据https://docs.python.org/3/reference/lexical_analysis.html#integer-literals:

整数文字由以下词汇定义描述:

integer        ::=  decimalinteger | octinteger | hexinteger | bininteger
decimalinteger ::=  nonzerodigit digit* | "0"+
nonzerodigit   ::=  "1"..."9"
digit          ::=  "0"..."9"
octinteger     ::=  "0" ("o" | "O") octdigit+
hexinteger     ::=  "0" ("x" | "X") hexdigit+
bininteger     ::=  "0" ("b" | "B") bindigit+
octdigit       ::=  "0"..."7"
hexdigit       ::=  digit | "a"..."f" | "A"..."F"
bindigit       ::=  "0" | "1"
Run Code Online (Sandbox Code Playgroud)

除了可以存储在可用内存中的内容之外,整数文字的长度没有限制.

请注意,不允许使用非零十进制数的前导零.这是为了消除C语言八进制文字,这是Python在3.0版之前使用的.

如此处所述,不允许使用非零十进制数的前导零."0"+合法是一个非常特殊的情况,在Python 2中没有:

integer        ::=  decimalinteger | octinteger | hexinteger | bininteger
decimalinteger ::=  nonzerodigit digit* | "0"
octinteger     ::=  "0" ("o" | "O") octdigit+ | "0" octdigit+
Run Code Online (Sandbox Code Playgroud)

SVN commit r55866在tokenizer中实现了PEP 3127,禁止使用旧0<octal>数字.然而,奇怪的是,它还添加了这个注释:

/* in any case, allow '0' as a literal */
Run Code Online (Sandbox Code Playgroud)

带有一个特殊nonzero标志,SyntaxError如果下面的数字序列包含非零数字,则仅抛出a .

这很奇怪,因为PEP 3127不允许这种情况:

这个PEP建议通过使用前导零指定八进制数的能力将从Python 3.0中的语言(以及2.6的Python 3.0预览模式)中删除,并且只要前导"0"是,就会引发SyntaxError.紧接着是另一个数字.

(强调我的)

因此,允许多个零的事实在技术上违反了PEP,并且基本上由Georg Brandl作为一个特例来实现.他做了相应的文档更改,注意这"0"+是一个有效的案例decimalinteger(以前已经涵盖在内octinteger).

我们可能永远不会确切知道为什么Georg选择使其"0"+有效 - 它可能永远是Python中的一个奇怪的角落.


更新 [2015年7月28日]:这个问题引发了一个关于python-ideas 的热烈讨论主题,其中Georg支持:

Steven D'Aprano写道:

为什么这样定义?[...]为什么我们写0000才能得到零?

我可以告诉你,但是我必须杀了你.

乔治·

后来,该线程产生了这个bug报告,旨在摆脱这种特殊情况.在这里,乔治说:

我不记得这种故意改变的原因(从文档变化中可以看出).

我现在无法想出这个改变的好理由[...]

因此我们拥有它:这种不一致背后的确切原因是时间的流逝.

最后,请注意错误报告被拒绝:对于Python 3.x的其余部分,仅在零整数上继续接受前导零.

  • 为什么这么说"我们可能永远都不知道格奥尔格为什么选择......"?如果知道他的人看到这个帖子并通知他,那么他可能会给出他的答案!(除非你知道他永远拒绝讨论他过去的Python工作或类似的情况) (6认同)
  • @GrandOpener:请注意,`001`是非法的,而您的解释会使其合法(因为"立即"的含义应该非常明确). (2认同)

Joh*_*ooy 17

这是一个特例("0"+)

2.4.4.整数文字

Integer literals are described by the following lexical definitions:

integer        ::=  decimalinteger | octinteger | hexinteger | bininteger
decimalinteger ::=  nonzerodigit digit* | "0"+
nonzerodigit   ::=  "1"..."9"
digit          ::=  "0"..."9"
octinteger     ::=  "0" ("o" | "O") octdigit+
hexinteger     ::=  "0" ("x" | "X") hexdigit+
bininteger     ::=  "0" ("b" | "B") bindigit+
octdigit       ::=  "0"..."7"
hexdigit       ::=  digit | "a"..."f" | "A"..."F"
bindigit       ::=  "0" | "1"

如果你看一下语法,就很容易看出0需要一个特殊情况.我不知道为什么' +'被认为是必要的.是时候挖掘开发邮件列表......


有趣的是,在Python2中,不止一个0被解析为octinteger(最终结果仍然0是)

decimalinteger ::=  nonzerodigit digit* | "0"
octinteger     ::=  "0" ("o" | "O") octdigit+ | "0" octdigit+