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


111

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
>>>

42
現在は削除できません。削除すると、この質問との下位互換性が失われます。
John La Rooy、2015

回答:


103

パー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"

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

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

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

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

SVNコミットr55866は、古い0<octal>番号を禁止するトークナイザに PEP 3127を実装しました。ただし、奇妙なことに、次のメモも追加されます。

/* in any case, allow '0' as a literal */

次の一連の数字にゼロ以外の数字が含まれてnonzeroいるSyntaxError場合にのみaをスローする特別なフラグを使用します。

PEP 3127はこのケースを許可しないため、これは奇妙です。

このPEPは、先行ゼロを使用して8進数を指定する機能がPython 3.0(およびPython 3.0プレビューモード2.6)の言語から削除され、先行 "0"が常にある場合はSyntaxErrorが発生することを提案しています。直後に別の数字が続く

(強調鉱山)

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

Georgが有効にすることを選択した理由を正確に知ることはおそらくないでしょう"0"+。Pythonで奇妙なコーナーケースがいつまでも残る可能性があります。


更新 [2015年7月28日]:この質問はpython-ideasに関する活発なディスカッションスレッドにつながり、Georgは次のように発言しました

Steven D'Apranoはこう書いている:

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

私はあなたに言うことができました、しかしそれから私はあなたを殺さなければなりませんでした。

ジョージ

後で、スレッドはこの特別なケースを取り除くことを目的としてこのバグレポートを生成しました。ここで、ジョージは言う

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

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

このように私たちはそれを持っています:この矛盾の背後にある正確な理由は時が経てば失われます。

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


6
なぜ「Georgが選んだ理由を正確に知ることは決してないだろう」と言うのですか?彼を知っている誰かがこのスレッドを見て、それについて彼に通知すると、彼は答えを返すかもしれません!(彼が過去のPythonの作業または同様の状況について話し合うことをずっと拒否していることをあなたが知っている場合を除いて)
セイウチ

1
彼らがなぜ2番目のPython 2 octintegerケースを作らなかったのか、私にはわかりません"0" octdigit*0C / C ++の8進数リテラルです。
Random832 2015

1
実際、英語はこの点で少しあいまいです。「別の」という言葉は「もう1つ」を意味することもあれば、「別のもの」を意味することもあります。PEP 3127からの太字の引用の有効な英語の解釈の1つは、「先頭の「0」の直後に「0」以外の数字が続く場合は常に、SyntaxErrorが発生する」ということです。それが実際に意図されていたかどうかはわかりません(その解釈は実際のコードでサポートされているように見えますが)いずれにしても、PEPがその文の追加の明確化なしに技術的に違反されていると言うのは正確ではないと私は思います。
GrandOpener 2015

2
@GrandOpener:これ001は違法であることに注意してください。あなたの解釈はそれを合法的にします(「すぐに」の意味は非常に明確でなければならないため)。
nneonneo

いい視点ね。したがって、PEPは間違いなく違反しています。あいまいなのは、違反される正確な性質です。:)
GrandOpener 2015

17

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

2.4.4。整数リテラル

整数リテラルは、次の字句定義によって記述されます。

整数:: = decimalinteger | オクティテガー| hexinteger | bininteger
decimalinteger :: =非ゼロ桁の数字* | 「0+」
ゼロ以外の桁:: = "1" ... "9"
数字:: = "0" ... "9"
octinteger :: = "0"( "o" | "O")octdigit +
hexinteger :: = "0"( "x" | "X")hexdigit +
bininteger :: = "0"( "b" | "B")bindigit +
オクテット:: = "0" ... "7"
16進数:::数字| 「a」...「f」| 「A」...「F」
bindigit :: = "0" | 「1」

文法を見ると0、特別なケースが必要であることが簡単にわかります。なぜ「+」が必要だと考えられているのかよくわかりません。開発メーリングリストを掘り下げる時間...


興味深いことに、Python2では1つ以上が0として解析されましたoctinteger(最終結果はまだ0です)。

decimalinteger :: =非ゼロ桁の数字* | 「0」
octinteger :: = "0"( "o" | "O")octdigit + | 「0」8進数+

1
そして、なぜあるのか"0"+、ないの"0"か?
lejlot 2015

1
@lejlot、まだです-しかし、私は興味をそそられます。それは間違いなく仕様の一部です
John La Rooy、2015

3

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

>>> 010
8

この(?誤解を招く)動作を回避するには、のpython3は、明示的な接頭辞を必要とし0b0o0x

>>> 0o10
8

15
問題は残ります:なぜ00許可されますか?(および0000000など)
Michael Geary 2015

4
@MichaelGeary:曖昧にすることはできないため(ベースに関係なく00000000は0です)、それを削除するとコードが不必要に壊れますか?まだ奇妙です。
RemcoGerlich 2015

5
@RemcoGerlich間違っていなければ、ベースに011関係ありません。
Holt

2
@Holt: "0" + "1"を許可しますか?特別なケースとしては、おそらくさらに混乱するでしょう。
RemcoGerlich 2015

4
@RemcoGerlich決してそうではないと言ったことはありません;)私は曖昧にすることもできないcan't be ambiguousので、これは議論ではないと言っていました01。IMO、その00ケースは特別なケース0です。
Holt
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.