2. 字句解析—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/2.7/reference/lexical analysis
移動先:案内検索

2.2。 字句解析

Pythonプログラムは、パーサーによって読み取られます。 パーサーへの入力は、字句解析プログラムによって生成されたトークンのストリームです。 この章では、字句解析プログラムがファイルをトークンに分割する方法について説明します。

Pythonは、プログラムテキストに7ビットのASCII文字セットを使用します。

バージョン2.3の新機能:エンコーディング宣言を使用して、文字列リテラルとコメントがASCIIとは異なるエンコーディングを使用することを示すことができます。


古いバージョンとの互換性のために、Pythonは8ビット文字が見つかった場合にのみ警告します。 これらの警告は、明示的なエンコーディングを宣言するか、これらのバイトが文字ではなくバイナリデータの場合はエスケープシーケンスを使用して修正する必要があります。

ランタイム文字セットは、プログラムに接続されているI / Oデバイスによって異なりますが、通常はASCIIのスーパーセットです。

将来の互換性に関する注意: 8ビット文字の文字セットはISOLatin-1(ラテンアルファベットを使用するほとんどの西洋言語をカバーするASCIIスーパーセット)であると思いがちですが、それは可能です。将来的にはUnicodeテキストエディタが一般的になるでしょう。 これらは通常、ASCIIスーパーセットでもあるUTF-8エンコーディングを使用しますが、序数128〜255の文字の使用法は大きく異なります。 このテーマについてはまだコンセンサスが得られていませんが、現在の実装ではLatin-1が優先されているように見えますが、Latin-1またはUTF-8のいずれかを想定することは賢明ではありません。 これは、ソース文字セットとランタイム文字セットの両方に適用されます。

2.1。 線の構造

Pythonプログラムは、いくつかの論理行に分割されています。

2.1.1。 論理行

論理行の終わりは、トークンNEWLINEで表されます。 ステートメントは、NEWLINEが構文で許可されている場合を除いて、論理行の境界を越えることはできません(たとえば、複合ステートメント内のステートメント間)。 論理ラインは、明示的または暗黙的なライン結合ルールに従って、1つ以上の物理ラインから構築されます。


2.1.2。 物理的な線

物理行は、行末シーケンスで終了する文字のシーケンスです。 ソースファイルと文字列では、標準のプラットフォーム行終了シーケンスのいずれかを使用できます-ASCII LF(改行)を使用するUnixフォーム、ASCIIシーケンスCR LF(リターンの後に改行)を使用するWindowsフォーム、またはを使用する古いMacintoshフォームASCII CR(リターン)文字。 プラットフォームに関係なく、これらのフォームはすべて等しく使用できます。 入力の終わりは、最終的な物理行の暗黙的なターミネータとしても機能します。

Pythonを埋め込む場合、改行文字の標準C規則を使用してソースコード文字列をPython APIに渡す必要があります(ASCIILFを表す\n文字は行末記号です)。


2.1.3。 コメント

コメントは、文字列リテラルの一部ではないハッシュ文字(#)で始まり、物理行の終わりで終わります。 コメントは、暗黙の行結合ルールが呼び出されない限り、論理行の終わりを示します。 コメントは構文によって無視されます。 それらはトークンではありません。


2.1.4。 エンコーディング宣言

Pythonスクリプトの1行目または2行目のコメントが正規表現coding[=:]\s*([-\w.]+)と一致する場合、このコメントはエンコード宣言として処理されます。 この式の最初のグループは、ソースコードファイルのエンコーディングに名前を付けます。 エンコーディング宣言は、独自の行に表示する必要があります。 2行目である場合、最初の行もコメントのみの行である必要があります。 エンコード式の推奨される形式は次のとおりです。

# -*- coding: <encoding-name> -*-

これはGNUEmacsでも認識されています。

# vim:fileencoding=<encoding-name>

これはBramMoolenaarのVIMによって認識されます。 さらに、ファイルの最初のバイトがUTF-8バイト順マーク('\xef\xbb\xbf')の場合、宣言されたファイルエンコーディングはUTF-8です(これは、特にMicrosoftのメモ帳でサポートされています)。 )。

エンコーディングが宣言されている場合、エンコーディング名はPythonによって認識される必要があります。 エンコーディングは、すべての字句解析、特に文字列の終わりを見つけるため、およびUnicodeリテラルの内容を解釈するために使用されます。 文字列リテラルは、構文分析のためにUnicodeに変換され、解釈が開始される前に元のエンコーディングに変換されます。


2.1.5。 明示的な線の結合

次のように、2つ以上の物理行を円記号(\)を使用して論理行に結合できます。物理行が文字列リテラルまたはコメントの一部ではない円記号で終わる場合、単一の論理行を形成した後、円記号とそれに続く行末文字を削除します。 例えば:

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

バックスラッシュで終わる行にはコメントを付けることはできません。 バックスラッシュはコメントを継続しません。 バックスラッシュは、文字列リテラルを除いてトークンを継続しません(つまり、文字列リテラル以外のトークンは、バックスラッシュを使用して物理行に分割することはできません)。 文字列リテラルの外側の行の他の場所では、円記号は無効です。


2.1.6。 暗黙のライン結合

括弧、角括弧、または中括弧内の式は、円記号を使用せずに複数の物理行に分割できます。 例えば:

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トークンはありません。 暗黙的に続く行は、トリプルクォートされた文字列内でも発生する可能性があります(以下を参照)。 その場合、コメントを載せることはできません。


2.1.7。 空白行

スペース、タブ、フォームフィード、および場合によってはコメントのみを含む論理行は無視されます(つまり、NEWLINEトークンは生成されません)。 ステートメントの対話型入力中、空白行の処理は、read-eval-printループの実装によって異なる場合があります。 標準の実装では、完全に空白の論理行(つまり、 空白やコメントさえ含まないもの)は、複数行のステートメントを終了します。


2.1.8。 インデント

論理行の先頭にある先頭の空白(スペースとタブ)は、行のインデントレベルを計算するために使用され、次に、ステートメントのグループ化を決定するために使用されます。

まず、タブが1〜8個のスペースに(左から右に)置き換えられ、置き換えを含む文字の総数が8の倍数になります(これは、Unixで使用されるのと同じルールであることが意図されています)。 次に、最初の空白以外の文字の前にあるスペースの総数によって、行のインデントが決まります。 インデントは、円記号を使用して複数の物理行に分割することはできません。 最初の円記号までの空白がインデントを決定します。

クロスプラットフォーム互換性に関する注意: UNIX以外のプラットフォームでのテキストエディタの性質上、単一のソースファイルのインデントにスペースとタブを組み合わせて使用することは賢明ではありません。 プラットフォームが異なると、最大インデントレベルが明示的に制限される場合があることにも注意してください。

行の先頭にフォームフィード文字が存在する場合があります。 上記のインデント計算では無視されます。 先頭の空白の他の場所にあるフォームフィード文字には、未定義の影響があります(たとえば、スペースカウントをゼロにリセットする場合があります)。

連続する行のインデントレベルは、次のように、スタックを使用してINDENTトークンとDEDENTトークンを生成するために使用されます。

ファイルの最初の行が読み取られる前に、単一のゼロがスタックにプッシュされます。 これは二度と飛び出すことはありません。 スタックにプッシュされる数は、常に下から上に厳密に増加します。 各論理行の先頭で、行のインデントレベルがスタックの最上位と比較されます。 それが等しい場合、何も起こりません。 大きい場合はスタックにプッシュされ、1つのインデントトークンが生成されます。 小さい場合は、スタックで発生する数値の1つである必要があります。 スタック上の大きい方のすべての番号がポップオフされ、ポップオフされた番号ごとに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のインデントは、スタックからポップされたレベルと一致しません。)


2.1.9。 トークン間の空白

論理行の先頭または文字列リテラルを除いて、空白文字のスペース、タブ、およびフォームフィードは、トークンを区切るために交換可能に使用できます。 2つのトークンの間に空白が必要になるのは、それらの連結が別のトークンとして解釈される可能性がある場合のみです(たとえば、abは1つのトークンですが、abは2つのトークンです)。


2.2。 その他のトークン

NEWLINE、INDENT、DEDENTの他に、識別子キーワードリテラル演算子のトークンのカテゴリがあります。区切り文字。 空白文字(前述の行末記号以外)はトークンではありませんが、トークンを区切るのに役立ちます。 あいまいさが存在する場合、トークンは、左から右に読み取られたときに、正当なトークンを形成する可能な限り長い文字列で構成されます。


2.3。 識別子とキーワード

識別子(名前とも呼ばれます)は、次の字句定義によって記述されます。

識別子 ::=  (letter|"_") (letter | digit | "_")*
手紙     ::=  lowercase | uppercase
小文字  ::=  "a"..."z"
大文字  ::=  "A"..."Z"
桁      ::=  "0"..."9"

識別子の長さは無制限です。 ケースは重要です。

2.3.1。 キーワード

以下の識別子は、予約語または言語のキーワードとして使用されており、通常の識別子としては使用できません。 ここに書かれているとおりに正確に綴る必要があります。

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で変更: as および with を識別子として使用すると、警告がトリガーされます。 それらをキーワードとして使用するには、with_statementの将来の機能を有効にします。


バージョン2.6で変更: as および with は完全なキーワードです。


2.3.2。 識別子の予約済みクラス

特定のクラスの識別子(キーワード以外)には特別な意味があります。 これらのクラスは、先頭と末尾の下線文字のパターンによって識別されます。

_*

from module import *ではインポートされません。 特別な識別子_は、最後の評価の結果を格納するために対話型インタープリターで使用されます。 __ builtin __ モジュールに保存されます。 インタラクティブモードでない場合、_には特別な意味はなく、定義されていません。 セクションインポートステートメントを参照してください。

ノート

_という名前は、国際化と組み合わせて使用されることがよくあります。 この規則の詳細については、 gettext モジュールのドキュメントを参照してください。

__*__

システム定義の名前。 これらの名前は、インタプリタとその実装(標準ライブラリを含む)によって定義されます。 現在のシステム名については、特別なメソッド名セクションなどで説明されています。 Pythonの将来のバージョンでは、さらに多くのことが定義される可能性があります。 __*__の使用は、明示的に文書化された使用に従わない場合、警告なしに破損する可能性があります。

__*

クラスプライベート名。 このカテゴリの名前は、クラス定義のコンテキスト内で使用される場合、基本クラスと派生クラスの「プライベート」属性間の名前の衝突を回避するために、マングル形式を使用するように書き直されます。 セクション識別子(名前)を参照してください。


2.4。 リテラル

リテラルは、一部の組み込み型の定数値の表記です。

2.4.1。 文字列リテラル

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

文字列リテラル   ::=  [stringprefix](shortstring | longstring)
stringprefix    ::=  "r" | "u" | "ur" | "R" | "U" | "UR" | "Ur" | "uR"
                     | "b" | "B" | "br" | "Br" | "bR" | "BR"
ショートストリング     ::=  "'" shortstringitem* "'" | '"' shortstringitem* '"'
ロングストリング      ::=  "'''" 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>

これらのプロダクションで示されていない構文上の制限の1つは、 stringprefix と残りの文字列リテラルの間に空白が許可されないことです。 ソース文字セットは、エンコーディング宣言によって定義されます。 ソースファイルにエンコーディング宣言が指定されていない場合はASCIIです。 セクションエンコーディング宣言を参照してください。

平易な英語:文字列リテラルは、一致する一重引用符(')または二重引用符(")で囲むことができます。 これらは、3つの一重引用符または二重引用符の一致するグループで囲むこともできます(これらは一般に三重引用符で囲まれた文字列と呼ばれます)。 バックスラッシュ(\)文字は、改行、バックスラッシュ自体、引用文字など、特別な意味を持つ文字をエスケープするために使用されます。 文字列リテラルの前には、オプションで文字'r'または'R'を付けることができます。 このような文字列は raw文字列と呼ばれ、バックスラッシュエスケープシーケンスの解釈にさまざまなルールを使用します。 'u'または'U'のプレフィックスは、文字列をUnicode文字列にします。 Unicode文字列は、UnicodeコンソーシアムおよびISO10646で定義されているUnicode文字セットを使用します。 以下で説明するいくつかの追加のエスケープシーケンスは、Unicode文字列で使用できます。 Python2では'b'または'B'のプレフィックスは無視されます。 これは、リテラルがPython3でバイトリテラルになる必要があることを示します(例: コードが2to3で自動的に変換される場合)。 'u'または'b'プレフィックスの後に、'r'プレフィックスを付けることができます。

三重引用符で囲まれた文字列では、エスケープされていない改行と引用符が許可されます(保持されます)。ただし、行内の3つのエスケープされていない引用符は文字列を終了します。 (「引用符」は、文字列を開くために使用される文字です。 'または"のいずれか。)

'r'または'R'プレフィックスが存在しない限り、文字列内のエスケープシーケンスは、標準Cで使用されているものと同様のルールに従って解釈されます。 認識されるエスケープシーケンスは次のとおりです。

エスケープシーケンス 意味 ノート
\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ビットの16進値を持つ文字 xxxx (Unicodeのみ) (1)
\Uxxxxxxxx 32ビットの16進値を持つ文字 xxxxxxxx (Unicodeのみ) (2)
\v ASCII垂直タブ(VT)
\ooo 8進値の文字 ooo (3,5)
\xhh 16進値の文字 hh (4,5)

ノート:

  1. サロゲートペアの一部を形成する個々のコードユニットは、このエスケープシーケンスを使用してエンコードできます。
  2. この方法では任意のUnicode文字をエンコードできますが、Pythonが16ビットコード単位(デフォルト)を使用するようにコンパイルされている場合、Basic Multilingual Plane(BMP)外の文字はサロゲートペアを使用してエンコードされます。
  3. 標準Cと同様に、最大3桁の8進数が受け入れられます。
  4. 標準Cとは異なり、正確に2桁の16進数が必要です。
  5. 文字列リテラルでは、16進数と8進数のエスケープは、指定された値を持つバイトを示します。 バイトがソース文字セットの文字をエンコードする必要はありません。 Unicodeリテラルでは、これらのエスケープは、指定された値を持つUnicode文字を示します。

標準Cとは異なり、認識されないエスケープシーケンスはすべて文字列に変更されずに残されます。つまり、バックスラッシュは文字列に残されます。 (この動作はデバッグ時に役立ちます。エスケープシーケンスの入力を間違えると、結果の出力が壊れていると認識されやすくなります。)上記の表で「(Unicodeのみ)」とマークされたエスケープシーケンスは次のように分類されることに注意してください。 Unicode以外の文字列リテラルの認識されないエスケープのカテゴリ。

'r'または'R'プレフィックスが存在する場合、バックスラッシュに続く文字は変更されずに文字列に含まれ、すべてのバックスラッシュは文字列に残ります。 たとえば、文字列リテラルr"\n"は、円記号と小文字の'n'の2文字で構成されます。 文字列の引用符は円記号でエスケープできますが、円記号は文字列に残ります。 たとえば、r"\""は、円記号と二重引用符の2文字で構成される有効な文字列リテラルです。 r"\"は有効な文字列リテラルではありません(生の文字列でさえ、奇数の円記号で終了することはできません)。 具体的には、生の文字列を単一の円記号で終了することはできません(円記号は次の引用文字をエスケープするため)。 また、単一の円記号とそれに続く改行は、文字列の一部としての2つの文字として解釈され、行の継続としてはではなくとして解釈されることにも注意してください。

'r'または'R'プレフィックスを'u'または'U'プレフィックスと組み合わせて使用すると、\uXXXXおよび [ X126X]エスケープシーケンスは処理されますが、他のすべての円記号は文字列に残ります。 たとえば、文字列リテラルur"\u0062\n"は、「LATIN SMALL LETTER B」、「REVERSE SOLIDUS」、および「LATIN SMALLLETTERN」の3つのUnicode文字で構成されます。 バックスラッシュは、前のバックスラッシュでエスケープできます。 ただし、両方とも文字列に残ります。 その結果、\uXXXXエスケープシーケンスは、円記号の数が奇数の場合にのみ認識されます。


2.4.2。 文字列リテラルの連結

おそらく異なる引用規則を使用する、複数の隣接する文字列リテラル(空白で区切られる)が許可され、それらの意味はそれらの連結と同じです。 したがって、"hello" 'world'"helloworld"と同等です。 この機能を使用すると、必要な円記号の数を減らしたり、長い文字列を長い行に便利に分割したり、文字列の一部にコメントを追加したりできます。たとえば、次のようになります。

re.compile("[A-Za-z_]"       # letter or underscore
           "[A-Za-z0-9_]*"   # letter, digit or underscore
          )

この機能は構文レベルで定義されていますが、コンパイル時に実装されることに注意してください。 実行時に文字列式を連結するには、「+」演算子を使用する必要があります。 また、リテラル連結では、コンポーネントごとに異なる引用符スタイルを使用できることに注意してください(生の文字列と三重引用符で囲まれた文字列を混合する場合でも)。


2.4.3。 数値リテラル

数値リテラルには、単純整数、長整数、浮動小数点数、および虚数の4つのタイプがあります。 複素数リテラルはありません(複素数は、実数と虚数を加算することで形成できます)。

数値リテラルには符号が含まれていないことに注意してください。 -1のような句は、実際には単項演算子 '-'とリテラル1で構成される式です。


2.4.4。 整数および長整数リテラル

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

longinteger    ::=  integer ("l" | "L")
整数        ::=  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+
ゼロ桁以外   ::=  "1"..."9"
octdigit       ::=  "0"..."7"
bindigit       ::=  "0" | "1"
hexdigit       ::=  digit | "a"..."f" | "A"..."F"

長整数のサフィックスとして小文字'l'と大文字'L'の両方を使用できますが、文字'l'なので、常に'L'を使用することを強くお勧めします。数字'1'に非常に似ています。

表現可能な最大のプレーン整数(たとえば、32ビット算術を使用する場合は2147483647)を超えるプレーン整数リテラルは、代わりに長整数であるかのように受け入れられます。 1 使用可能なメモリに格納できるものを除いて、長整数リテラルに制限はありません。

プレーン整数リテラル(最初の行)と長整数リテラル(2行目と3行目)のいくつかの例:

7     2147483647                        0177
3L    79228162514264337593543950336L    0377L   0x100000000L
      79228162514264337593543950336             0xdeadbeef

2.4.5。 浮動小数点リテラル

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

floatnumber   ::=  pointfloat | exponentfloat
ポイントフロート    ::=  [intpart] fraction | intpart "."
exponentfloat ::=  (intpart | pointfloat) exponent
intpart       ::=  digit+
分数      ::=  "." digit+
指数      ::=  ("e" | "E") ["+" | "-"] digit+

浮動小数点数の整数部分と指数部分は8進数の整数のように見えますが、基数10を使用して解釈されることに注意してください。 たとえば、077e010は有効であり、77e10と同じ番号を示します。 浮動小数点リテラルの許容範囲は、実装によって異なります。 浮動小数点リテラルのいくつかの例:

3.14    10.    .001    1e100    3.14e-10    0e0

数値リテラルには符号が含まれていないことに注意してください。 -1のような句は、実際には単項演算子-とリテラル1で構成される式です。


2.4.6。 架空のリテラル

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

imagnumber ::=  (floatnumber | intpart) ("j" | "J")

虚数リテラルは、実数部が0.0の複素数を生成します。 複素数は浮動小数点数のペアとして表され、その範囲には同じ制限があります。 実数がゼロ以外の複素数を作成するには、(3+4j)のように浮動小数点数を追加します。 虚数リテラルのいくつかの例:

3.14j   10.j    10j     .001j   1e100j  3.14e-10j

2.5。 演算子

次のトークンは演算子です。

+       -       *       **      /       //      %
<<      >>      &       |       ^       ~
<       >       <=      >=      ==      !=      <>

比較演算子<>!=は、同じ演算子の代替スペルです。 !=が推奨されるスペルです。 <>は廃止されました。


2.6。 区切り文字

次のトークンは、文法の区切り文字として機能します。

(       )       [       ]       {       }      @
,       :       .       `       =       ;
+=      -=      *=      /=      //=     %=
&=      |=      ^=      >>=     <<=     **=

ピリオドは、浮動小数点リテラルおよび虚数リテラルでも発生する可能性があります。 3つのピリオドのシーケンスには、スライスの省略記号として特別な意味があります。 リストの後半である拡張代入演算子は、字句的に区切り文字として機能しますが、操作も実行します。

次の印刷ASCII文字は、他のトークンの一部として特別な意味を持っているか、字句解析プログラムにとって重要です。

'       "       #       \

次の印刷ASCII文字はPythonでは使用されません。 文字列リテラルとコメントの外部でのそれらの発生は、無条件のエラーです。

$       ?

脚注

1
2.4より前のバージョンのPythonでは、表現可能な最大のプレーン整数のすぐ上で、最大の符号なし32ビット数(32ビット演算を使用するマシン上)より下の範囲の8進数および16進数のリテラルが負のプレーンと見なされていました。符号なしの値から4294967296を引いて得られる整数。