7. 複合文 (compound statement)¶
複合文には、他の文 (のグループ) が入ります; 複合文は、中に入っている他の文の実行の制御に何らかのやり方で影響を及ぼします。一般的には、複合文は複数行にまたがって書かれますが、全部の文を一行に連ねた単純な書き方もあります。
if 、 while 、および for 文は、伝統的な制御フロー構成を実現します。 try は例外処理および / または一連の文に対するクリーンアップコードを指定します。関数とクラス定義もまた、構文法的には複合文です。
複合文は、一つまたはそれ以上の ' 節 (clause)' からなります。一つの節は、ヘッダと ' スイート (suite)' からなります。特定の複合文を構成する節のヘッダ部分は、全て同じインデントレベルになります。各々の節ヘッダ行は一意に識別されるキーワードから始まり、コロンで終わります。スイートは、ヘッダのコロンの後ろにセミコロンで区切られた一つまたはそれ以上の単純文を並べるか、ヘッダ行後のインデントされた文の集まりです。後者の形式のスイートに限り、ネストされた複合文を入れることができます ; 以下の文は、 else 節がどの if 節に属するかがはっきりしないという理由から不正になります :
if test1: if test2: print x
また、このコンテキスト中では、セミコロンはコロンよりも強い結合を表すことにも注意してください。従って、以下の例では、 print は全て実行されるか、されないかのどちらかです
if x < y < z: print x; print y; print z
まとめると、以下のようになります:
compound_stmt ::=if_stmt|while_stmt|for_stmt|try_stmt|with_stmt|funcdef|classdef|decoratedsuite ::=stmt_listNEWLINE | NEWLINE INDENTstatement+ DEDENT statement ::=stmt_listNEWLINE |compound_stmtstmt_list ::=simple_stmt(";"simple_stmt)* [";"]
文は常に NEWLINE か、その後に DEDENT が続いたもので終了することに注意してください。また、オプションの継続節は常にあるキーワードから始まり、このキーワードから複合文を開始することはできないため、曖昧さは存在しないことにも注意してください (Python では、 ' ぶら下がり (dangling) else' 問題を、ネストされた if 文はインデントさせること解決しています ) 。
以下の節における文法規則の記述方式は、明確さのために、各節を別々の行に書くようにしています。
7.1. if 文¶
if 文は、条件分岐を実行するために使われます:
if_stmt ::= "if"expression":"suite( "elif"expression":"suite)* ["else" ":"suite]
if 文は、式を一つ一つ評価してゆき、真になるまで続けて、真になった節のスイートだけを選択します (真: true と偽: false の定義については、 ブール演算 (boolean operation) 節を参照してください); 次に、選択したスイートを実行します (そして、 if 文の他の部分は、実行や評価をされません)。全ての式が偽になった場合、 else 節があれば、そのスイートが実行されます。
7.2. while 文¶
while 文は、式の値が真である間、実行を繰り返すために使われます:
while_stmt ::= "while"expression":"suite["else" ":"suite]
while 文は式を繰り返し真偽評価し、真であれば最初のスイートを実行します。式が偽であれば (最初から偽になっていることもありえます)、 else 節がある場合にはそれを実行し、ループを終了します。
最初のスイート内で break 文が実行されると、 else 節のスイートを実行することなくループを終了します。 continue 文が最初のスイート内で実行されると、スイート内にある残りの文の実行をスキップして、式の真偽評価に戻ります。
7.3. for 文¶
for 文は、シーケンス (文字列、タプルまたはリスト) や、その他の反復可能なオブジェクト (iterable object) 内の要素に渡って反復処理を行うために使われます:
for_stmt ::= "for"target_list"in"expression_list":"suite["else" ":"suite]
式リストは一度だけ評価されます ; 結果はイテレーション可能オブジェクトにならねばなりません。 expression_list の結果に対してイテレータを生成し、その後、シーケンスの各要素についてインデクスの小さい順に一度だけスイートを実行します。このときシーケンス内の要素が通常の代入規則を使ってターゲットリストに代入され、その後スイートが実行されます。全ての要素を使い切ると ( シーケンスが空の場合にはすぐに ) 、 else 節があればそれが実行され、ループを終了します。
最初のスイート内で break 文が実行されると、 else 節のスイートを実行することなくループを終了します。 continue 文が最初のスイート内で実行されると、スイート内にある残りの文の実行をスキップして、次の要素の処理に移るか、これ以上次の要素が無い場合は else 節の処理に移ります。
スイートの中では、ターゲットリスト内の変数に代入を行えます; この代入によって、次に代入される要素に影響を及ぼすことはありません。
ループが終了してもターゲットリストは削除されませんが、シーケンスが空の場合には、ループでの代入は全く行われません。ヒント : 組み込み関数 range() は、 Pascal 言語における for i := a to b do の効果をエミュレートするのに適した数列を返します ; すなわち、 range(3) はリスト [0, 1, 2] を返します。
注釈
ループ中のシーケンスの変更には微妙な問題があります ( これは変更可能なシーケンス、すなわちリストで起こります ) 。どの要素が次に使われるかを追跡するために、内部的なカウンタが使われており、このカウンタは反復処理を行うごとに加算されます。このカウンタがシーケンスの長さに達すると、ループは終了します。このことは、スイート中でシーケンスから現在の ( または以前の ) 要素を除去すると、 ( 次の要素のインデクスは、すでに取り扱った要素のインデクスになるために ) 次の要素が飛ばされることを意味します。同様に、スイート中でシーケンス中の現在の要素以前に要素を挿入すると、ループ中で現在の要素が再度扱われることになります。こうした仕様は、厄介なバグになります。シーケンス全体に相当するスライスを使って一時的なコピーを作ると、これを避けることができます。
for x in a[:]:
if x < 0: a.remove(x)
7.4. try 文¶
try 文は、ひとまとめの文に対して、例外処理および/またはクリーンアップコードを指定します:
try_stmt ::= try1_stmt | try2_stmt try1_stmt ::= "try" ":"suite("except" [expression[("as" | ",")identifier]] ":"suite)+ ["else" ":"suite] ["finally" ":"suite] try2_stmt ::= "try" ":"suite"finally" ":"suite
バージョン 2.5 で変更: 以前のバージョンの Python では、 try… except… finally は機能しませんでした。 try… except は try… finally 中でネストさせる必要がありました。
except 節は一つ以上の例外ハンドラを指定します。 try 節内で例外が起きなければ、どの例外ハンドラも実行されません。 try スイート内で例外が発生すると、例外ハンドラの検索が開始されます。この検索では、 except 節を逐次、発生した例外に対応するまで調べます。式を伴わない except 節を使うなら、最後に書かなければならず、これは全ての例外に対応します。式を伴う except 節に対しては、その式が評価され、結果のオブジェクトが例外と "互換である (compatible)" 場合にその節が対応します。ある例外に対してオブジェクトが互換であるのは、それが例外オブジェクトのクラスかベースクラスの場合、または例外と互換である要素が入ったタプルである場合です。
例外がどの except 節にも合致しなかった場合、現在のコードを囲うさらに外側、そして呼び出しスタックへと検索を続けます。 [1]
except 節のヘッダにある式を値評価するときに例外が発生すると、元々のハンドラ検索はキャンセルされ、新たな例外に対する例外ハンドラの検索を現在の except 節の外側のコードや呼び出しスタックに対して行います (try 文全体が例外を発行したかのように扱われます)。
合致する except 節が見つかると、その except 節はその except 節で指定されているターゲットに代入されて、もし存在する場合、加えて except 節スイートが実行されます。全ての except 節は実行可能なブロックを持っていなければなりません。このブロックの末尾に到達すると、通常は try 文全体の直後に実行を継続します。 ( このことは、同じ例外に対してネストした二つの例外ハンドラが存在し、内側のハンドラ内の try 節で例外が発生した場合、外側のハンドラは例外を処理しないことを意味します。 )
except 節のスイートが実行される前に、例外に関する詳細が sys モジュール内の三つの変数に代入されます : sys.exc_type は、例外を示すオブジェクトを受け取ります ; sys.exc_value は例外のパラメタを受け取ります ; sys.exc_traceback は、プログラム上の例外が発生した位置を識別するトレースバックオブジェクト (標準型の階層 参照 ) を受け取ります。これらの詳細はまた、関数 sys.exc_info() を介して入手することもできます。この関数はタプル (exc_type, exc_value, exc_traceback) を返します。ただしこの関数に対応する変数の使用は、スレッドを使ったプログラムで安全に使えないため撤廃されています。 Python 1.5 からは、例外を処理した関数から戻るときに、以前の値 ( 関数呼び出し前の値 ) に戻されます。
オプションの else 節は、実行の制御が try 節の末尾に到達した場合に実行されます。 [2] else 節内で起きた例外は、 else 節に先行する except 節で処理されることはありません。
finally 節がある場合は、 '後始末 (cleanup)' の対処を指定します。まず except 節や else 節を含め、 try 節が実行されます。それらの節の中で例外が起き、誰も対処していない場合は、例外は一時的に保存されます。次に finally 節が実行されます。保存された例外があった場合は、 finally 節の末尾で再送出されます。 finally 節で別の例外が送出される場合、あるいは return, break 文を実行した場合は、保存された例外は破棄されます:
>>> def f():
... try:
... 1/0
... finally:
... return 42
...
>>> f()
42
finally 節を実行している間は、プログラムからは例外情報は利用できません。
try…finally 文の try スイート内で return 、 break 、または continue 文が実行された場合、 finally 節も '抜け出る途中に (on the way out)' 実行されます。 finally 節での continue 文の使用は不正です。 (理由は現在の実装上の問題です – この制限は将来解消されるかもしれません)。
関数の返り値は最後に実行された return 文によって決まります。
finally 節は必ず実行されるため、finally 節で実行された return 文は常に最後に実行されます:
>>> def foo():
... try:
... return 'try'
... finally:
... return 'finally'
...
>>> foo()
'finally'
例外に関するその他の情報は 例外 節にあります。また、 raise 文の使用による例外の生成に関する情報は、 raise 文 節にあります。
7.5. with 文¶
バージョン 2.5 で追加.
with 文は、ブロックの実行を、コンテキストマネージャによって定義されたメソッドでラップするために使われます( with文とコンテキストマネージャ セクションを参照してください)。これにより、よくある try…except…finally 利用パターンをカプセル化して便利に再利用することができます。
with_stmt ::= "with" with_item ("," with_item)* ":" suite
with_item ::= expression ["as" target]
一つの "要素" を持つ with 文の実行は以下のように進行します:
コンテキスト式 (
with_itemで与えられた式) を評価することで、コンテキストマネージャを取得します。コンテキストマネージャの
__exit__()メソッドが、後で使うためにロードされます。コンテキストマネージャの
__enter__()メソッドが呼ばれます。with文にターゲットが含まれていたら、それに__enter__()からの戻り値が代入されます。注釈
with文は、__enter__()メソッドがエラーなく終了した場合には__exit__()が常に呼ばれることを保証します。ですので、もしエラーがターゲットリストへの代入中にエラーが発生した場合には、これはそのスイートの中で発生したエラーと同じように扱われます。以下のステップ 6 を参照してください。スイートが実行されます。
コンテキストマネージャの
__exit__()メソッドが呼ばれます。もし例外がスイートを終了させる場合、その型、値、そしてトレースバックが__exit__()へ引数として渡されます。そうでなければ、 3 つのNone引数が与えられます。スイートが例外により終了され、
__exit__()メソッドからの戻り値が偽( false )ならば、例外が再送出されます。この戻り値が真( true )ならば例外は抑制され、実行はwith文の次の文から続きます。もしそのスイートが例外でない何らかの理由で終了した場合、その
__exit__()からの戻り値は無視されて、実行は発生した終了の種類に応じた通常の位置から継続します。
複数の要素があるとき、コンテキストマネージャは複数の with 文がネストされたかのように進行します:
with A() as a, B() as b:
suite
は、以下と同等です
with A() as a:
with B() as b:
suite
注釈
Python 2.5 では、 with 文は with_statement 機能が有効にされた場合にだけ利用できます。 Python 2.6 では常に利用できます。
バージョン 2.7 で変更: 複数のコンテキスト式をサポートしました。
7.6. 関数定義¶
関数定義は、ユーザ定義関数オブジェクトを定義します (標準型の階層 節参照):
decorated ::= decorators (classdef | funcdef) decorators ::=decorator+ decorator ::= "@"dotted_name["(" [argument_list[","]] ")"] NEWLINE funcdef ::= "def"funcname"(" [parameter_list] ")" ":"suitedotted_name ::=identifier("."identifier)* parameter_list ::= (defparameter",")* ( "*"identifier["," "**"identifier] | "**"identifier|defparameter[","] ) defparameter ::=parameter["="expression] sublist ::=parameter(","parameter)* [","] parameter ::=identifier| "("sublist")" funcname ::=identifier
関数定義は実行可能な文です。関数定義を実行すると、現在のローカルな名前空間内で関数名を関数オブジェクト (関数の実行可能コードをくるむラッパ) に束縛します。この関数オブジェクトには、関数が呼び出された際に使われるグローバルな名前空間として、現在のグローバルな名前空間への参照が入っています。
関数定義は関数本体を実行しません; 関数本体は関数が呼び出された時にのみ実行されます。 [3]
関数定義は一つ以上のデコレータ (decorator) 式でラップできます。デコレータ式は関数を定義するとき、関数定義の入っているスコープで評価されます。その結果は、関数オブジェクトを唯一の引数にとる呼び出し可能オブジェクトでなければなりません。関数オブジェクトの代わりに、返された値が関数名に束縛されます。複数のデコレータはネストして適用されます。例えば、以下のようなコード
@f1(arg)
@f2
def func(): pass
は、以下と同じです
def func(): pass
func = f1(arg)(f2(func))
一つ以上のトップレベルの parameters に parameter = expression の形式がある場合、関数は " デフォルトのパラメタ値 (default parameter values)" を持つといいます。デフォルト値を伴うパラメタに対しては、関数呼び出しの際に対応する引数(argument)が省略されると、パラメタの値はデフォルト値で置き換えられます。あるパラメタがデフォルト値を持つ場合、それ以後のパラメタは全てデフォルト値を持たなければなりません — これは文法的には表現されていない構文上の制限です。
** デフォルトパラメタ値は関数定義を実行する際に値評価されます。 ** これは、デフォルトパラメタの式は関数を定義するときにただ一度だけ評価され、同じ " 計算済みの " 値が全ての呼び出しで使われることを意味します。デフォルトパラメタ値がリストや辞書のような変更可能なオブジェクトである場合、この使用を理解しておくことは特に重要です : 関数でこのオブジェクトを ( 例えばリストに要素を追加して ) 変更すると、実際のデフォルト値が変更されてしまいます。一般には、これは意図しない動作です。このような動作を避けるには、デフォルト値に None を使い、この値を関数本体の中で明示的にテストします。例えば以下のようにします
def whats_on_the_telly(penguin=None):
if penguin is None:
penguin = []
penguin.append("property of the zoo")
return penguin
関数呼び出しの意味付けに関する詳細は、 呼び出し (call) 節で述べられています。関数呼び出しを行うと、パラメタリストに記述された全てのパラメタに対して、固定引数、キーワード引数、デフォルト引数のいずれかから値を代入します。 "*identifier" 形式が存在する場合、余った固定引数を受け取るタプルに初期化されます。この変数のデフォルト値は空のタプルです。 "**identifier" 形式が存在する場合、余ったキーワード引数を受け取るタプルに初期化されます。デフォルト値は空の辞書です。
式で直接使うために、無名関数 ( 名前に束縛されていない関数 ) を作成することも可能です。無名関数の作成には、 ラムダ (lambda) 節で記述されているラムダ式 (lambda expression) を使います。ラムダ式は、単純化された関数定義を行うための略記法にすぎません ; "def" 文で定義された関数は、ラムダ式で定義された関数と全く同様に引渡したり、他の名前に代入したりできます。実際には、 "def" 形式は複数の式を実行できるという点でより強力です。
** プログラマのための注釈 :** 関数は一級の (first-class) オブジェクトです。関数定義内で "def" 形式を実行すると、戻り値として返したり引き渡したりできるローカルな関数を定義します。ネストされた関数内で自由変数を使うと、 def 文の入っている関数のローカル変数にアクセスすることができます。詳細は 名前づけと束縛 (naming and binding) 節を参照してください。
7.7. クラス定義¶
クラス定義は、クラスオブジェクトを定義します (標準型の階層 節参照):
classdef ::= "class"classname[inheritance] ":"suiteinheritance ::= "(" [expression_list] ")" classname ::=identifier
クラス定義は実行可能な文です。クラス定義では、まず継承リストがあればそれを評価します。継承リストの各要素の値評価結果はクラスオブジェクトか、サブクラス可能なクラス型でなければなりません。次にクラスのスイートが新たな実行フレーム内で、新たなローカル名前空間と元々のグローバル名前空間を使って実行されます (名前づけと束縛 (naming and binding) 節を参照してください ) 。 ( 通常、スイートには関数定義のみが含まれます ) クラスのスイートを実行し終えると、実行フレームは無視されますが、ローカルな名前空間は保存されます。次に、基底クラスの継承リストを使ってクラスオブジェクトが生成され、ローカルな名前空間を属性値辞書として保存します。最後に、もとのローカルな名前空間において、クラス名がこのクラスオブジェクトに束縛されます。
** プログラマのための注釈 :** クラス定義内で定義された変数はクラス変数です ; クラス変数は全てのインスタンス間で共有されます。インスタンス変数を作成するには、メソッドの中で self.name = value でセットできます。クラス変数もインスタンス変数も "self.name" 表記でアクセスすることができます。この表記でアクセスする場合、インスタンス変数は同名のクラス変数を隠蔽します。クラス変数は、インスタンス変数のデフォルト値として使えますが、変更可能な値をそこに使うと予期せぬ結果につながります。新スタイルクラス (new-style class) では、デスクリプタを使ってインスタンス変数の振舞いを変更できます。
クラス定義は、関数定義と同じように、 1 つ以上のデコレータ (decorator) 式でラップすることができます。デコレータ式の評価規則は関数と同じです。結果はクラスオブジェクトでなければならず、それがクラス名に束縛されます。
注記
| [1] | 例外は、別の例外を送出するような finally 節が無い場合にのみ呼び出しスタックへ伝わります。新しい例外によって、古い例外は失われます。 |
| [2] | 現在、制御が "末尾に到達する" のは、例外が発生したり、 return, continue, または break 文が実行される場合を除きます。 |
| [3] | 関数の本体の最初の文として現われる文字列リテラルは、その関数の __doc__ 属性に変換され、その関数のドキュメンテーション文字列(docstring) になります。 |
| [4] | クラスの本体の最初の文として現われる文字列リテラルは、その名前空間の __doc__ 要素となり、そのクラスのドキュメンテーション文字列(docstring)になります。 |
