Python で書かれたプログラムは パーザ (parser) に読み込まれます。パーザへの入力は、 字句解析器 (lexical analyzer) によって生成された一連の トークン (token) からなります。この章では、字句解析器がファイルをトークン列に分解する方法について解説します。
Python は 7-bit の ASCII 文字セットをプログラムのテキストに使います。
バージョン 2.3 で追加: エンコード宣言を使って、文字列リテラルやコメントに ASCII ではない文字セットが使われていることを明示できます。.
以前のバージョンとの互換性のために、Python は 8-bit 文字が見つかっても警告を出すだけにとどめます; こうした警告は、エンコーディングを明示したり、バイナリデータの場合には文字ではなくエスケープシーケンスを使うことで解決できます。
実行時の文字セットは、プログラムが接続されている I/O デバイスにもよりますが、通常 ASCIIのサブセットです。
将来のバージョンとの互換性に関する注意: 8-bit 文字に対する文字セットを ISO Latin-1 (ラテン語系アルファベットを用いるほとんどの西欧言語をカバーするASCII の上位セット) とみなしたい気にもなるかもしれません。しかし、おそらく Unicode を編集できるテキストエディタが将来一般的になるはずです。こうしたエディタでは一般的に UTF-8 エンコードを使いますが、UTF-8 エンコードは ASCII の上位セットではあるものの、文字序数 (ordinal) 128-255 の扱いが非常に異なります。この問題に関してはまだ合意が得られていませんが、 Latin-1 と UTF-8 のどちらかとみなすのは、たとえ現在の実装が Latin-1 びいきのように思えたとしても賢明とはいえません。これはソースコード文字セットと実行時の文字セットのどちらにも該当します。
Python プログラムは多数の 論理行 (logical lines) に分割されます。
論理行の終端は、トークン NEWLINE で表されます。構文上許されている場合 (複合文: compound statement 中の実行文: statement) を除いて、実行文は論理行間にまたがることはできません。論理行は一行またはそれ以上の 物理行(physical line) からなり、物理行の末尾には明示的または非明示的な 行連結(line joining) 規則が続きます。
物理行とは、行終端コードで区切られた文字列のことです。ソースコード内では、各プラットフォームごとの標準の行終端コードを使用することができます。 Unix形式ではASCII LF (行送り: linefeed)文字、 Windows形式ではASCII 配列の CR LF (復帰: return に続いて行送り) 、 Macintosh形式ではASCII CR (復帰) 文字です。これら全ての形式のコードは、違うプラットフォームでも等しく使用することができます。
Pythonに埋め込む場合には、標準のC言語の改行文字の変換規則 (ASCII LFを表現した文字コード \n が行終端となります) に従って、 Python APIにソースコードを渡す必要があります。
コメントは文字列リテラル内に入っていないハッシュ文字 (#) から始まり、同じ物理行の末端で終わります。非明示的な行継続規則が適用されていない限り、コメントは論理行を終端させます。コメントは構文上無視されます; コメントはトークンになりません。
Python スクリプト中の最初の行か、二行目にあるコメントが正規表現 coding[=:]\s*([-\w.]+) にマッチする場合、コメントはエンコード宣言 (encoding declaration) として処理されます; 表現に対する最初のマッチグループがソースコードファイルのエンコードを指定します。エンコード宣言式として推奨する形式は、GNU Emacs が認識できる形式
# -*- coding: <encoding-name> -*-
または、Bram Moolenar による VIM が認識できる形式
# vim:fileencoding=<encoding-name>
です。さらに、ファイルの先頭のバイト列が UTF-8 バイトオーダ記号 ('\xef\xbb\xbf') の場合、ファイルのエンコードは UTF-8 と宣言されているものとします (この機能は Microsoft の notepad やその他のエディタでサポートされています)。
エンコードが宣言されている場合、Python はそのエンコード名を認識できなければなりません。宣言されたエンコードは全ての字句解析、特に文字列の終端を検出する際や Unicode リテラルの内容を翻訳する上で用いられます。文字列リテラルは文法的な解析を行うために Unicode に変換され、解釈が行われる前に元のエンコードに戻されます。エンコード宣言は宣言全体が一行に収まっていなければなりません。
二つまたはそれ以上の物理行を論理行としてつなげるためには、バックスラッシュ文字 (\) を使って以下のようにします: 物理行が文字列リテラルやコメント中の文字でないバックスラッシュで終わっている場合、後続する行とつなげて一つの論理行を構成し、バックスラッシュおよびバックスラッシュの後ろにある行末文字を削除します。例えば:
if 1900 < year < 2100 and 1 <= month <= 12 \
and 1 <= day <= 31 and 0 <= hour < 24 \
and 0 <= minute < 60 and 0 <= second < 60: # Looks like a valid date
return 1
となります。
バックスラッシュで終わる行にはコメントを入れることはできません。また、バックスラッシュを使ってコメントを継続することはできません。バックスラッシュが文字列リテラル中にある場合を除き、バックスラッシュの後ろにトークンを継続することはできません (すなわち、物理行内の文字列リテラル以外のトークンをバックスラッシュを使って分断することはできません)。上記以外の場所では、文字列リテラル外にあるバックスラッシュはどこにあっても不正となります。
丸括弧 (parentheses)、角括弧 (square bracket) 、および波括弧 (curly brace) 内の式は、バックスラッシュを使わずに一行以上の物理行に分割することができます。例えば:
month_names = ['Januari', 'Februari', 'Maart', # These are the
'April', 'Mei', 'Juni', # Dutch names
'Juli', 'Augustus', 'September', # for the months
'Oktober', 'November', 'December'] # of the year
非明示的に継続された行にはコメントを含めることができます。継続行のインデントは重要ではありません。空の継続行を書くことができます。非明示的な継続行中には、NEWLINE トークンは存在しません。非明示的な行の継続は、三重クオートされた文字列 (下記参照) でも発生します; この場合には、コメントを含めることができません。
スペース、タブ、フォームフィード、およびコメントのみを含む論理行は無視されます (すなわち、NEWLINE トークンは生成されません)。文を対話的に入力している際には、空行の扱いは行読み込み-評価-出力 (read-eval-print) ループの実装によって異なるかもしれません。標準的な実装では、完全な空行でできた論理行 (すなわち、空白文字もコメントも全く含まない空行) は、複数行からなる実行文の終端を示します。
論理行の行頭にある、先頭の空白 (スペースおよびタブ) の連なりは、その行のインデントレベルを計算するために使われます。インデントレベルは、実行文のグループ化方法を決定するために用いられます。
まず、タブは (左から右の方向に) 1 つから 8 つのスペースで置き換えられ、置き換え後の文字列の終わりの位置までの文字数が 8 の倍数になるように調整されます (Unixで使われている規則と同じになるよう意図されています)。次に、空白文字でない最初の文字までのスペースの総数から、その行のインデントを決定します。バックスラッシュを使ってインデントを複数の物理行に分割することはできません; 最初のバックスラッシュまでの空白がインデントを決定します。
プラットフォーム間の互換性に関する注意: 非 UNIX プラットフォームにおけるテキストエディタの性質上、一つのソースファイル内でタブとインデントを混在させて使うのは賢明ではありません。また、プラットフォームによっては、最大インデントレベルを明示的に制限しているかもしれません。
フォームフィード文字が行の先頭にあっても構いません; フォームフィード文字は上のインデントレベル計算時には無視されます。フォームフィード文字が先頭の空白中の他の場所にある場合、その影響は未定義です (例えば、スペースの数を 0 にリセットするかもしれません)。
連続する行における各々のインデントレベルは、 INDENT および DEDENT トークンを生成するために使われます。トークンの生成はスタックを用いて以下のように行われます。
ファイル中の最初の行を読み出す前に、スタックにゼロが一つ積まれ (push され) ます; このゼロは決して除去 (pop) されることはありません。スタックの先頭に積まれてゆく数字は、常にスタックの末尾から先頭にかけて厳密に増加するようになっています。各論理行の開始位置において、その行のインデントレベル値がスタックの先頭の値と比較されます。値が等しければ何もしません。インデントレベル値がスタック上の値よりも大きければ、インデントレベル値はスタックに積まれ、INDENT トークンが一つ生成されます。インデントレベル値がスタック上の値よりも小さい場合、その値はスタック内のいずれかの値と 等しくなければなりません ; スタック上のインデントレベル値よりも大きい値はすべて除去され、値が一つ除去されるごとに DEDENT トークンが一つ生成されます。ファイルの末尾では、スタックに残っているゼロより大きい値は全て除去され、値が一つ除去されるごとに DEDENT トークンが一つ生成されます。
以下の例に正しく (しかし当惑させるように) インデントされた Python コードの一部を示します:
def perm(l):
# Compute the list of all permutations of l
if len(l) <= 1:
return [l]
r = []
for i in range(len(l)):
s = l[:i] + l[i+1:]
p = perm(s)
for x in p:
r.append(l[i:i+1] + x)
return r
以下の例は、様々なインデントエラーになります:
def perm(l): # error: first line indented
for i in range(len(l)): # error: not indented
s = l[:i] + l[i+1:]
p = perm(l[:i] + l[i+1:]) # error: unexpected indent
for x in p:
r.append(l[i:i+1] + x)
return r # error: inconsistent dedent
(実際は、最初の 3 つのエラーはパーザによって検出されます; 最後のエラーのみが字句解析器で見つかります — return r のインデントは、スタックから逐次除去されていくどのインデントレベル値とも一致しません)
論理行の先頭や文字列の内部にある場合を除き、空白文字であるスペース、タブ、およびフォームフィードは、トークンを分割するために自由に利用することができます。二つのトークンを並べて書くと別のトークンとしてみなされてしまうような場合には、トークンの間に空白が必要となります (例えば、ab は一つのトークンですが、 a b は二つのトークンとなります)。
NEWLINE、INDENT、および DEDENT の他、以下のトークンのカテゴリ: 識別子 (identifier), キーワード(keyword), リテラル, 演算子 (operator), デリミタ (delimiter) が存在します。空白文字 (上で述べた行終端文字以外) はトークンではありませんが、トークンを区切る働きがあります。トークンの解析にあいまいさが生じた場合、トークンは左から右に読んで不正でないトークンを構築できる最長の文字列を含むように構築されます。
識別子 (または 名前 (name)) は、以下の字句定義で記述されます:
identifier ::= (letter|"_") (letter | digit | "_")* letter ::= lowercase | uppercase lowercase ::= "a"..."z" uppercase ::= "A"..."Z" digit ::= "0"..."9"
識別子の長さには制限がありません。大小文字は区別されます。
以下の識別子は、予約語、または Python 言語における キーワード (keyword) として使われ、通常の識別子として使うことはできません。キーワードは厳密に下記の通りに綴らなければなりません:
and del from not while
as elif global or with
assert else if pass yield
break except import print
class exec in raise
continue finally is return
def for lambda try
バージョン 2.4 で変更: このバージョンから None は定数になり、 組み込みオブジェクト None の名前としてコンパイラに認識されるようになりました。これは予約語ではありませんが、 これに他のオブジェクトを割り当てることはできません。
バージョン 2.5 で変更: with_statement 機能をfuture文によって有効にしたときにのみ、 キーワード as と with は認識されます。 この機能はPython 2.6で正式に有効になる予定です。詳しくは、 with 文 節を参照してください。 as と with を識別子として使用した場合は、 たとえfuture文で with_statement が有効になっていなかったとしても常にワーニングが表示されます。
ある種の (キーワードを除く) 識別子には、特殊な意味があります。これらの識別子種は、先頭や末尾にあるアンダースコア文字のパターンで区別されます:
この識別子は from module import * で import されません。対話インタプリタでは、最も最近行われた値評価の結果を記憶するために特殊な識別子 _ が使われます; この識別子は __builtin__ モジュール内に記憶されます。対話モードでない場合、 _ には特殊な意味はなく、定義されていません。 import 文 を参照してください。
ノート
名前 _ は、しばしば国際化 (internationalization) と共に用いられます; この慣習についての詳しい情報は、 gettext 参照してください。
リテラル (literal) とは、いくつかの組み込み型の定数を表記したものです。
文字列リテラルは以下の字句定義で記述されます:
stringliteral ::= [stringprefix](shortstring | longstring) stringprefix ::= "r" | "u" | "ur" | "R" | "U" | "UR" | "Ur" | "uR" shortstring ::= "'" shortstringitem* "'" | '"' shortstringitem* '"' longstring ::= "'''" longstringitem* "'''" | '"""' longstringitem* '"""' shortstringitem ::= shortstringchar | escapeseq longstringitem ::= longstringchar | escapeseq shortstringchar ::= <any source character except "\" or newline or the quote> longstringchar ::= <any source character except "\"> escapeseq ::= "\" <any ASCII character>
上記の生成規則で示されていない文法的な制限が一つあります。それは文字列リテラルの stringprefix と残りの部分の間に空白を入れてはならないということです。ソースコード文字セット (source character set) はエンコード宣言で決まります.エンコード宣言がない場合には ASCII になります. エンコード宣言 (encoding declaration) 節を参照してください.
より平易な説明: 文字列リテラルは、対応する一重引用符 (') または二重引用符 (") で囲われます。また、対応する三連の一重引用符や二重引用符で囲うこともできます (通常、 三重クオート文字列: triple-quoted string として参照されます)。バックスラッシュ (\) 文字を使って、ある文字を例えば改行文字やバックスラッシュ自体、クオート文字といった別の意味を持つようにエスケープすることができます。文字列リテラルの前には、オプションとして 'r' または 'R' 一文字を接頭してもかまいません; このような文字列は raw 文字列 (raw string) と呼ばれ、バックスラッシュによるエスケープシーケンスの解釈規則が異なります。 'u' や 'U' を接頭すると、文字列は Unicode 文字列 (Unicode string) になります。Unicode 文字列は Unicode コンソーシアムおよび ISO 10646 で定義されている Unicode 文字セットを使います。Unicode 文字列では、文字セットに加えて、以下で説明するようなエスケープシーケンスを利用できます。二つの接頭文字を組み合わせることもできます; この場合、 'u' は 'r' より前に出現しなくてはなりません。
三重クオート文字列中には、三連のエスケープされないクオート文字で文字列を終端してしまわないかぎり、エスケープされていない改行やクオートを書くことができます (さらに、それらはそのまま文字列中に残ります)。 (ここでいう “クオート” とは、文字列の囲みを開始するときに使った文字を示し、 ' か " のいずれかです)。
'r' または 'R' 接頭文字がつかないかぎり、文字列中のエスケープシーケンスは標準 C で使われているのと同様の法則にしたがって解釈されます。以下に Python で認識されるエスケープシーケンスを示します:
エスケープシーケンス | 意味 | 備考 |
---|---|---|
\newline | 無視 | |
\\ | バックスラッシュ (\) | |
\' | 一重引用符 (') | |
\" | 二重引用符 (") | |
\a | ASCII 端末ベル (BEL) | |
\b | ASCII バックスペース (BS) | |
\f | ASCII フォームフィード (FF) | |
\n | ASCII 行送り (LF) | |
\N{name} | Unicode データベース中で名前 name を持つ文字 (Unicode のみ) | |
\r | ASCII 復帰 (CR) | |
\t | ASCII 水平タブ (TAB) | |
\uxxxx | 16-bit の 16 進数値 xxxx を持つ文字 (Unicode のみ) | (1) |
\Uxxxxxxxx | 32-bit の 16 進数値 xxxxxxxx を持つ文字 (Unicode のみ) | (2) |
\v | ASCII 水平タブ (VT) | |
\ooo | 8 進数値 ooo を持つ文字 | (3,5) |
\xhh | 16 進数値 hh を持つ文字 | (4,5) |
備考:
標準の C とは違い、認識されなかったエスケープシーケンスはそのまま文字列中に残されます。すなわち。 バックスラッシュも文字列中に残ります。 (この挙動はデバッグの際に便利です: エスケープシーケンスを誤入力した場合、その結果として出力に失敗しているのが用意にわかります) テーブル中で “(Unicode のみ)” と書かれたエスケープシーケンスは、非 Unicode 文字列リテラル中では認識されないエスケープシーケンスのカテゴリに分類されるので注意してください。
接頭文字 'r' または 'R' がある場合、バックスラッシュの後にくる文字はそのまま文字列中に入り、*バックスラッシュは全て文字列中に残されます*。例えば、文字列リテラル r"\n" は二つの文字: バックスラッシュと小文字の 'n' からなる文字列を表すことになります。引用符はバックスラッシュでエスケープすることができますが、バックスラッシュ自体も残ってしまいます; 例えば、 r"\"" は不正でない文字列リテラルで、バックスラッシュと二重引用符からなる文字列を表します; r"\" は正しくない文字列リテラルです (raw 文字列を奇数個連なったバックスラッシュで終わらせることはできません)。厳密にいえば、 (バックスラッシュが直後のクオート文字をエスケープしてしまうため) raw文字列を単一のバックスラッシュで終わらせることはできない ということになります。また、バックスラッシュの直後に改行がきても、行継続を意味する のではなく 、それら二つの文字として解釈されるので注意してください。
'r' および 'R' 接頭文字を 'u' や 'U' と合わせて使った場合、 \uXXXX および \UXXXXXXXX エスケープシーケンスは処理されますが、 その他のバックスラッシュはすべて文字列中に残されます 。例えば、文字列リテラル ur"\u0062\n" は、3つの Unicode 文字: ‘LATIN SMALL LETTER B’ (ラテン小文字 B)、’REVERSE SOLIDUS’ (逆向き斜線)、および ‘LATIN SMALL LETTER N’ (ラテン小文字 N) を表します。バックスラッシュの前にバックスラッシュをつけてエスケープすることはできます; しかし、バックスラッシュは両方とも文字列中に残されます。その結果、 \uXXXX エスケープシーケンスは、バックスラッシュが奇数個連なっている場合にのみ認識されます。
複数の文字列リテラルは、互いに異なる引用符を使っていても (空白文字で区切って) 隣接させることができ、その意味は各々の文字列を結合したものと同じになります。したがって、 "hello" 'world' は "helloworld" と同じになります。この機能を使うと、長い文字列を分離して、複数行にまたがらせる際に便利です。また、部分文字列ごとにコメントを追加することもできます。例えば:
re.compile("[A-Za-z_]" # letter or underscore
"[A-Za-z0-9_]*" # letter, digit or underscore
)
この機能は文法レベルで定義されていますが、スクリプトをコンパイルする際の処理として実現されることに注意してください。実行時に文字列表現を結合したければ、 ‘+’ 演算子を使わなければなりません。また、リテラルの結合においては、結合する各要素に異なる引用符形式を使える (raw 文字列と三重引用符を混ぜることさえできます) ので注意してください。
数値リテラルは 4 種類あります: 整数 (plain integer)、長整数 (long integer)、浮動小数点数 (floating point number)、そして虚数 (imaginary number) です。複素数のためのリテラルはありません (複素数は実数と虚数の和で作ることができます)。
数値リテラルには符号が含まれていないことに注意してください; -1 のような句は、実際には単項演算子 (unary operator) ‘-‘ とリテラル 1 を組み合わせたものです。
整数および長整数リテラルは以下の字句定義で記述されます:
longinteger ::= integer ("l" | "L") integer ::= decimalinteger | octinteger | hexinteger | bininteger decimalinteger ::= nonzerodigit digit* | "0" octinteger ::= "0" ("o" | "O") octdigit+ | "0" octdigit+ hexinteger ::= "0" ("x" | "X") hexdigit+ bininteger ::= "0" ("b" | "B") bindigit+ nonzerodigit ::= "1"..."9" octdigit ::= "0"..."7" bindigit ::= "0" | "1" hexdigit ::= digit | "a"..."f" | "A"..."F"
長整数を表す末尾の文字は小文字の 'l' でも大文字の 'L' でもかまいませんが、 'l' は '1' に良く似ているので、常に 'L' を使うよう強く勧めます。
整数で表現できる最大の値よりも大きい整数のリテラル (例えば 32-bit 整数を使っている場合には 2147483647) は、長整数として表現できる値であれば受理されます。 [1] 値がメモリ上に収まるかどうかという問題を除けば、長整数リテラルには値域の制限がありません。
整数リテラル (最初の行) と長整数リテラル (二行目および三行目) の例を以下に示します:
7 2147483647 0177
3L 79228162514264337593543950336L 0377L 0x100000000L
79228162514264337593543950336 0xdeadbeef
浮動小数点数リテラルは以下の字句定義で記述されます:
floatnumber ::= pointfloat | exponentfloat pointfloat ::= [intpart] fraction | intpart "." exponentfloat ::= (intpart | pointfloat) exponent intpart ::= digit+ fraction ::= "." digit+ exponent ::= ("e" | "E") ["+" | "-"] digit+
浮動小数点数における整数部と指数部は 8 進数のように見えることもありますが、10 を基数として解釈されるので注意してください。例えば、 077e010 は正しい表記であり、 77e10 と同じ数を表します。浮動小数点数リテラルの取りうる値の範囲は実装に依存します。浮動小数点数リテラルの例をいくつか示します:
3.14 10. .001 1e100 3.14e-10 0e0
数値リテラルには符号が含まれていないことに注意してください; -1 のような句は、実際には単項演算子 (unary operator) ‘-‘ とリテラル 1 を組み合わせたものです。
虚数リテラルは以下のような字句定義で記述されます:
imagnumber ::= (floatnumber | intpart) ("j" | "J")
虚数リテラルは、実数部が 0.0 の複素数を表します。複素数は二つ組の浮動小数点型の数値で表され、それぞれの数値は浮動小数点型と同じ定義域の範囲を持ちます。実数部がゼロでない浮動小数点を生成するには、 (3+4j) のように虚数リテラルに浮動小数点数を加算します。以下に虚数リテラルの例をいくつか示します:
3.14j 10.j 10j .001j 1e100j 3.14e-10j
以下のトークンは演算子です:
+ - * ** / // %
<< >> & | ^ ~
< > <= >= == != <>
比較演算子 <> と != は、同じ演算子について別の書き方をしたものです。書き方としては != を推奨します; <> は時代遅れの書き方です。
以下のトークンは文法上のデリミタとして働きます:
( ) [ ] { } @
, : . ` = ;
+= -= *= /= //= %=
&= |= ^= >>= <<= **=
浮動小数点数や虚数リテラル中にピリオドがあってもかまいません。ピリオド三つの列はスライス表記における省略符号 (ellipsis) として特別な意味を持っています。リスト後半の累算代入演算子 (augmented assignment operator) は、字句的にはデリミタとして振舞いますが、演算も行います。
以下の印字可能 ASCII 文字は、他のトークンの一部として特殊な意味を持っていたり、字句解析器にとって重要な意味を持っています:
' " # \
以下の印字可能 ASCII 文字は、Python では使われていません。これらの文字が文字列リテラルやコメントの外にある場合、無条件にエラーとなります:
$ ?
Footnotes
[1] | バージョン 2.4 以前の Python では, 8 進および 16 進のリテラルのうち,通常の整数型として表現可能な値より大きく,かつ符号無しの 32-bit (32-bit 演算を使う計算機の場合) 整数で表現できる最大値,すなわち 4294967296 よりも小さな数は,リテラルを符号無し整数として表現した値から 4294967296 を引いて得られる負の整数として扱っていました. |