115

なぜ 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
>>>
4

3 に答える 3

106

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

ここで述べたように、ゼロ以外の10 進数の先行ゼロは許可されません。Python 2 には存在しなかっ"0"+た非常に特殊なケースとして正当です:

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 は、先行ゼロを使用して 8 進数を指定する機能が Python 3.0 (および 2.6 の Python 3.0 プレビュー モード) の言語から削除され、先行 "0" が使用されるたびに SyntaxError が発生することを提案しています。直後に別の数字が続きます。

(私のものを強調)

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

Georg が有効にすることを選択した理由を正確に知ることはおそらくないでしょう- それは Python では永遠に奇妙なコーナーケースであり続けるかもしれません."0"+


更新[2015 年 7 月 28 日]: この質問は、Python のアイデアに関する活発なディスカッション スレッドにつながりまし

スティーブン・ダプラノは次のように書いています。

なぜそのように定義されたのですか?[...] ゼロを取得するために 0000 を書き込むのはなぜですか?

私はあなたに言うことができたが、それなら私はあなたを殺さなければならないだろう.

ゲオルク

その後、スレッドはこの特殊なケースを取り除くことを目的として、このバグ レポートを作成しました。ここで、Georg は次のように述べています。

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

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

この不一致の背後にある正確な理由は、時間の経過とともに失われます。

最後に、バグ レポートが却下されたことに注意してください。Python 3.x の残りの部分では、先行ゼロは引き続きゼロ整数でのみ受け入れられます。

于 2015-07-16T08:01:29.323 に答える
2

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

>>> 010
8

この (誤解を招く?) 動作を回避するために、Python3 では明示的なプレフィックス0b, 0o,が必要0xです。

>>> 0o10
8
于 2015-07-16T07:26:56.700 に答える