为什么Python 3允许“00”作为0的文字而不允许“01”作为1的文字?
为什么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 >>>
根据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"+
作为一个非常特殊的情况是合法的, 在Python 2中不存在 :
integer ::= decimalinteger | octinteger | hexinteger | bininteger decimalinteger ::= nonzerodigit digit* | "0" octinteger ::= "0" ("o" | "O") octdigit+ | "0" octdigit+
SVN commit r55866在tokenizer中实现了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预览模式)中被移除,并且每当前导“0”被引发时,将会引发SyntaxError紧接着是另一个数字 。
(重点是我的)
所以,允许多个零的这个事实在技术上违反了PEP,并且基本上由Georg Brandl作为一个特例来实现。 他做了相应的文档更改,注意到"0"+
是decimalinteger
octinteger
的有效情况(之前已经在octinteger
下octinteger
)。
我们可能永远不知道为什么Georgselect使"0"+
有效 – 它可能永远在Python中仍然是一个奇怪的angular落案例。
更新 [2015年7月28日]:这个问题引发了一个关于python思想的热烈讨论 , Georg在其中提到 :
Steven D'Aprano写道:
为什么这样定义? […]为什么我们会写0000来获得零?
我可以告诉你,但是我不得不杀了你。
乔治·
后来,线程产生了这个错误报告,旨在摆脱这种特殊情况。 Georg在这里说 :
我不记得这个故意改变的原因(从文档改变看)。
我现在无法想出这个改变的一个好的理由[…]
因此我们拥有了:这种不一致背后的确切原因已经失去了时间。
最后,请注意,这个错误报告被拒绝了:对于其他的Python 3.x而言,前导零将仅被接受为零整数。
这是一个特例( "0"+
)
2.4.4。 整数文字
整数文字用下面的词汇定义来描述: 整数:: =十进制整数| octinteger | hexinteger | bininteger decimalinteger :: = nonzerodigit数字* | “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
被parsing为一个octinteger
(最终结果仍然是0
)
decimalinteger :: = nonzerodigit数字* | “0” octinteger :: =“0”(“o”|“O”)十进制+ | “0”octdigit +
Python2使用前导零来指定八进制数字:
>>> 010 8
为了避免这种(误导?)行为,Python3需要明确的前缀0b
, 0o
, 0x
:
>>> 0o10 8