为什么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
>>>
答案 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"+
)
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需要明确的前缀0b
,0o
,0x
:
>>> 0o10
8