Why does Python 3 allow "00" as a literal for 0 but not allow "01" as a literal for 1?

Why does Python 3 allow "00" as a literal for 0 but not allow "01" as a literal for 1? Is there a good reason? This inconsistency baffles me. (And we're talking about Python 3, which purposely broke backward compatibility in order to achieve goals like consistency.)

For example:

>>> from datetime import time
>>> time(16, 00)
datetime.time(16, 0)
>>> time(16, 01)
File "<stdin>", line 1
time(16, 01)
^
SyntaxError: invalid token
>>>
10336 次浏览

Python2使用前导零来指定八进制数:

>>> 010
8

To avoid this (misleading?) behaviour, Python3 requires explicit prefixes 0b, 0o, 0x:

>>> 0o10
8

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

2.4.4. Integer literals

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需要一个特殊的情况。我不知道为什么“ +”被认为是必要的,虽然。是时候查看开发人员邮件列表了..。


值得注意的是,在 Python 2中,多个 0被解析为 octinteger(但最终结果仍然是 0)

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

Per 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"

整数字面值的长度没有限制,除了 can be stored in available memory.

注意,不允许在非零小数中使用前导零。 这是为了使用 C 样式的八进制文字消除歧义,其中 Python 在3.0版本前使用。

正如这里指出的,non-zero小数中的前导零是不允许的。"0"+作为一个非常特殊的案例是合法的,wasn't present in Python 2:

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

SVN 提交 r55866 在标记器中实现了 PEP 3127,它禁止使用旧的 0<octal>编号。然而,奇怪的是,它还补充了一点:

/* in any case, allow '0' as a literal */

使用一个特殊的 nonzero标志,只有在下列数字序列包含非零数字时才抛出 SyntaxError

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

这个 PEP 建议从 Python 3.0(以及 Python 3.0预览模式2.6)和 当前导“0”后立即跟随另一个数字时,将引发 SyntaxError中删除使用前导零来指定八进制数的能力。

(强调我的)

因此,允许多个零的事实是 严格来说违反了 PEP,基本上是由 Georg Brandl 作为特例实现的。他对相应的文档进行了修改,注意到 "0"+decimalinteger的有效案例(以前在 octinteger中讨论过)。

我们可能永远不会知道为什么 Georg 选择使 "0"+有效——它可能永远是 Python 中一个奇怪的角落案例。


更新 [2015年7月28日] : 这个问题导致了一个关于 python 的 活跃的讨论话题——其中 盖尔插话了:

史蒂文 · 德 · 阿普拉诺写道:

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

I could tell you, but then I'd have to kill you.

盖尔

后来,这个线程产生了 this bug report,目的是摆脱这种特殊情况。这里,盖尔说:

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

我现在想不出一个好的理由来解释这个变化[ ... ]

因此,我们得出了这样的结论: 这种不一致背后的确切原因已经被时间遗忘了。

最后,请注意 bug 报告被拒绝了: 在 Python 3.x 的其余部分中,前导零将继续只在零整数上被接受。