1. ホーム
  2. python

[解決済み] Python 3は0を表すリテラルとして "00 "を許し、1を表すリテラルとして "01 "を許さないのはなぜか?

2022-10-14 12:33:09

質問

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

どのように解決するのですか?

以下の通りです。 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進数リテラルと曖昧さをなくすためのものです。 がバージョン3.0より前に使用していたC言語の8進数リテラルとの曖昧さをなくすためです。

ここに書かれているように、先頭のゼロは 非ゼロ の先頭のゼロは許されません。 "0"+ は非常に特殊なケースとして合法であり、これは は Python 2 には存在しませんでした。 :

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 は Python 3.0 (および 2.6 の Python 3.0 プレビューモード) の言語から、先頭の 0 を使って 8 進数を指定する機能を削除することを提案しており、そのために を指定した場合、SyntaxError が発生します。 .

(強調)

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

私たちはおそらく知る由もない 正確に なぜゲオルグが "0"+ を有効にした理由です。これは Python の奇妙なコーナーケースのままかもしれません。


アップデイト [2015年7月28日】の記事です。] この質問により 活発な議論スレッド にて、python-ideasで Georg が参加しました。 :

<ブロッククオート

Steven D'Aprano さんが書き込みました。

<ブロッククオート

なぜそのように定義されたのでしょうか?[...] なぜゼロを得るために0000と書かなければならないのでしょうか?

教えてあげてもいいけど、そしたらあなたを殺さなきゃいけないから。

ゲオルグ

その後、このスレッドから生まれた このバグレポート は、この特殊なケースを取り除くことを目的としています。これを ゲオルグのコメント :

<ブロッククオート

この意図的な変更の理由は覚えていません(docsの変更から見て)。

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

というわけで、この矛盾の背後にある正確な理由は、時間の経過とともに失われているのです。

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