web-dev-qa-db-ja.com

なぜPython 3は0のリテラルとして "00"を許可するが、1のリテラルとして "01"を許可しないのですか?

なぜPython 3は0のリテラルとして "00"を許可しますが、1のリテラルとして "01"を許可しませんか?正当な理由はありますか?この矛盾は私を困惑させます。 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
>>>
107
walrus

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"

使用可能なメモリに格納できるものを除いて、整数リテラルの長さに制限はありません。

ゼロ以外の10進数の先行ゼロは許可されないことに注意してください。これは、Cスタイルの8進リテラルとのあいまいさを解消するためのもので、バージョン3.0以前ではPythonが使用されていました。

ここで述べたように、non-zero 10進数の先行ゼロは許可されていません。 "0"+は非常に特殊なケースとして正当であり、 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では、先頭のゼロを使用して8進数を指定する機能を、Python 3.0(およびPython 3.0プレビューモード2.6)、およびそのSyntaxErrorは、先頭の「0」の直後に別の数字が続くときに発生します.

(エンファシス鉱山)

したがって、複数のゼロが許可されているという事実は技術的に PEPに違反しており、基本的にGeorg Brandlによる特別なケースとして実装されました。彼は"0"+decimalinteger(以前はoctintegerでカバーされていた)の有効なケースであることに注意するために、対応するドキュメントを変更しました。

exactly Georgが"0"+を有効にすることを選択した理由は、おそらく決してわかりません。


[〜#〜] update [〜#〜][2015年7月28日]:この質問は 活発な議論スレッド につながりました Georg chimed in :python-ideasで

スティーブン・ダプラノはこう書いている:

なぜそのように定義されたのですか? [...]なぜ0000を書いてゼロを取得するのでしょうか?

私はあなたに伝えることができますが、その後、私はあなたを殺さなければなりません。

ゲオルグ

後で、スレッドが生成されました このバグレポート この特殊なケースを取り除くことを目指しています。ここでは、 Georg says

この意図的な変更の理由は思い出せません(ドキュメントの変更からわかるように)。

私は今、この変更の正当な理由を思い付くことができません[...]

このように、この矛盾の背後にある正確な理由は時を経て失われます。

最後に、バグレポートが拒否されたことに注意してください。先頭のゼロは、残りのPython 3.x.

100
nneonneo

特別なケースです("0"+

2.4.4。整数リテラル

整数リテラルは、次の字句定義によって記述されます。
 
 integer :: = decimalinteger |オクト整数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では、複数の0octintegerとして解析されたことに注意してください(結果はまだ0ですが)

 decimalinteger :: =非ゼロ桁の数字* | "0" 
 octinteger :: = "0"( "o" | "O")octdigit + | "0" octdigit + 
17
John La Rooy

Python2は、先行ゼロを使用して8進数を指定しました。

>>> 010
8

この(誤解を招く可能性のある)動作を避けるために、Python3では明示的なプレフィックス0b0o0x

>>> 0o10
8
4
dlask