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

时间:2015-07-16 07:18:20

标签: python python-3.x integer literals 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
>>>

3 个答案:

答案 0 :(得分:100)

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"
     

除了什么之外,整数文字的长度没有限制   可存储在可用内存中。

     

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

如上所述,不允许非零十进制数中的前导零。 "0"+作为一个非常特殊的案例是合法的,wasn't present in Python 2

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

SVN commit r55866在令牌化程序中实施了PEP 3127,禁止使用旧0<octal>个号码。然而,奇怪的是,它还添加了这个注释:

/* in any case, allow '0' as a literal */
带有特殊nonzero标记的

如果以下数字序列包含非零数字,则仅抛出SyntaxError

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

  

这个PEP建议通过使用前导零来指定八进制数的能力将从Python 3.0中的语言(以及2.6的Python 3.0预览模式)中删除,并且每次都会引发一个SyntaxError一个领先的&#34; 0&#34;紧接着是另一个数字

(强调我的)

因此,允许多个零的事实技术上违反了PEP,并且基本上由Georg Brandl作为一个特例来实现。他对相应的文档进行了更改,以指出"0"+decimalinteger的有效案例(以前已在octinteger中涵盖过)。

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

更新 [2015年7月28日]:这个问题导致了lively discussion thread关于python-ideas的问题Georg chimed in

  

Steven D&#39; Aprano写道:

     
    

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

  
     

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

     

乔治

稍后,线程产生this bug report旨在摆脱这种特殊情况。在这里,Georg says

  

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

     

我现在无法提出这个改变的充分理由[...]

因此我们拥有它:这种不一致背后的确切原因已经消失了。

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

答案 1 :(得分:17)

这是一个特例("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需要一个特例。我不确定为什么'+'被认为是必要的。是时候挖掘开发邮件列表......

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

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

答案 2 :(得分:5)

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

>>> 010
8

为了避免这种(误导?)行为,Python3需要明确的前缀0b0o0x

>>> 0o10
8