7。 複合ステートメント
複合ステートメントには、他のステートメント(のグループ)が含まれます。 それらは、何らかの方法でそれらの他のステートメントの実行に影響を与えるか、または制御します。 一般に、複合ステートメントは複数の行にまたがりますが、単純な化身では、複合ステートメント全体が1行に含まれる場合があります。
if 、 while 、および for ステートメントは、従来の制御フロー構造を実装します。 try は、ステートメントのグループの例外ハンドラーやクリーンアップコードを指定します。 関数とクラスの定義も構文的に複合ステートメントです。
複合ステートメントは、1つ以上の「句」で構成されます。 句は、ヘッダーと「スイート」で構成されます。 特定の複合ステートメントの句ヘッダーはすべて同じインデントレベルにあります。 各句ヘッダーは、一意に識別するキーワードで始まり、コロンで終わります。 スイートは、句によって制御されるステートメントのグループです。 スイートは、ヘッダーのコロンに続く、ヘッダーと同じ行にある1つ以上のセミコロンで区切られた単純なステートメントにすることも、後続の行にある1つ以上のインデントされたステートメントにすることもできます。 ネストされた複合ステートメントを含めることができるのは、後者の形式のスイートのみです。 以下は違法です。これは主に、後続の 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 | decorated スイート ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT 声明 ::= stmt_list NEWLINE | compound_stmt stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
ステートメントは常にNEWLINE
で終わり、その後にDEDENT
が続く可能性があることに注意してください。 また、オプションの継続句は常にステートメントを開始できないキーワードで始まるため、あいまいさはありません(Pythonでは、ネストされた if ステートメントを要求することで「ぶら下がり else 」の問題が解決されます)インデントされます)。
次のセクションの文法規則のフォーマットでは、わかりやすくするために各句を別々の行に配置しています。
7.1。 NS もしも声明
if ステートメントは、条件付き実行に使用されます。
if_stmt ::= "if" expression ":" suite ( "elif" expression ":" suite )* ["else" ":" suite]
1つがtrueであることが判明するまで、式を1つずつ評価することにより、スイートの1つを正確に選択します(trueとfalseの定義については、セクションブール演算を参照してください)。 次に、そのスイートが実行されます( if ステートメントの他の部分は実行または評価されません)。 すべての式がfalseの場合、 else 句のスイートが存在する場合は実行されます。
7.2。 NS その間声明
while ステートメントは、式が真である限り、繰り返し実行するために使用されます。
while_stmt ::= "while" expression ":" suite ["else" ":" suite]
これは式を繰り返しテストし、それがtrueの場合、最初のスイートを実行します。 式がfalseの場合(初めてテストされる場合があります)、 else 句のスイートが存在する場合は実行され、ループが終了します。
最初のスイートで実行された break ステートメントは、 else 句のスイートを実行せずにループを終了します。 最初のスイートで実行された continue ステートメントは、スイートの残りの部分をスキップして、式のテストに戻ります。
7.3。 NS にとって声明
for ステートメントは、シーケンスの要素(文字列、タプル、リストなど)またはその他の反復可能なオブジェクトを反復処理するために使用されます。
for_stmt ::= "for" target_list "in" expression_list ":" suite ["else" ":" suite]
式リストは1回評価されます。 反復可能なオブジェクトを生成する必要があります。 expression_list
の結果に対してイテレータが作成されます。 次に、イテレータによって提供されたアイテムごとに、インデックスの昇順でスイートが1回実行されます。 各アイテムは、割り当ての標準ルールを使用してターゲットリストに順番に割り当てられ、スイートが実行されます。 アイテムが使い果たされると(シーケンスが空になるとすぐに)、 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。 NS 試す声明
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 にネストする必要がありました。
exception 句は、1つ以上の例外ハンドラーを指定します。 try 句で例外が発生しない場合、例外ハンドラーは実行されません。 try スイートで例外が発生すると、例外ハンドラーの検索が開始されます。 この検索では、例外に一致するものが見つかるまで、except句が順番に検査されます。 式のないexcept句が存在する場合は、最後にする必要があります。 すべての例外に一致します。 式を含むexcept句の場合、その式が評価され、結果のオブジェクトが例外と「互換性がある」場合、句は例外と一致します。 オブジェクトが例外オブジェクトのクラスまたは基本クラスである場合、または例外と互換性のある項目を含むタプルである場合、そのオブジェクトは例外と互換性があります。
例外に一致するexcept句がない場合、例外ハンドラーの検索は、周囲のコードと呼び出しスタックで続行されます。 1
例外句のヘッダーにある式の評価で例外が発生した場合、ハンドラーの元の検索はキャンセルされ、周囲のコードと呼び出しスタックで新しい例外の検索が開始されます(全体として扱われます)。 try ステートメントで例外が発生しました)。
一致するexcept句が見つかると、そのexcept句で指定されているターゲットに例外が割り当てられ、存在する場合は、except句のスイートが実行されます。 句を除くすべての句には、実行可能ブロックが必要です。 このブロックの終わりに達すると、tryステートメント全体の後で通常どおり実行が続行されます。 (これは、同じ例外に対して2つのネストされたハンドラーが存在し、例外が内部ハンドラーのtry句で発生した場合、外部ハンドラーは例外を処理しないことを意味します。)
例外句のスイートが実行される前に、例外に関する詳細が sys モジュールの3つの変数に割り当てられます。sys.exc_type
は例外を識別するオブジェクトを受け取ります。 sys.exc_value
は例外のパラメーターを受け取ります。 sys.exc_traceback
は、例外が発生したプログラム内のポイントを識別するトレースバックオブジェクト(セクション標準タイプ階層を参照)を受け取ります。 これらの詳細は、タプル(exc_type, exc_value, exc_traceback)
を返す sys.exc_info()関数からも入手できます。 対応する変数の使用は、スレッド化されたプログラムでは安全ではないため、この関数を優先して非推奨になりました。 Python 1.5以降、例外を処理した関数から戻ると、変数は(呼び出し前の)以前の値に復元されます。
オプションの else 句は、制御フローが try スイートを離れ、例外が発生せず、 return 、 Continue 、または break ステートメントが実行されました。 else 句の例外は、先行する exception 句では処理されません。
最終的にが存在する場合は、「クリーンアップ」ハンドラーを指定します。 try 句が実行されます。これには、および else 句を除くすべての句が含まれます。 いずれかの句で例外が発生し、処理されない場合、例外は一時的に保存されます。 finally 句が実行されます。 保存された例外がある場合は、 finally 句の最後で再発生します。 finally 句で別の例外が発生するか、 return または break ステートメントを実行すると、保存された例外は破棄されます。
>>> def f():
... try:
... 1/0
... finally:
... return 42
...
>>> f()
42
finally 句の実行中は、プログラムは例外情報を利用できません。
return 、 break または continue ステートメントが、 try …の try スイートで実行された場合] finally ステートメント、 finally 句も '途中で'実行されます。 continue ステートメントは finally 句では無効です。 (理由は、現在の実装に問題があるためです。この制限は将来解除される可能性があります)。
関数の戻り値は、最後に実行された return ステートメントによって決定されます。 finally 句は常に実行されるため、 finally 句で実行される return ステートメントは常に最後に実行されます。
>>> def foo():
... try:
... return 'try'
... finally:
... return 'finally'
...
>>> foo()
'finally'
例外に関する追加情報はセクション Exceptions にあり、 raise ステートメントを使用して例外を生成する方法に関する情報はセクション raiseステートメントにあります。
7.5。 NS と声明
バージョン2.5の新機能。
with ステートメントは、コンテキストマネージャーによって定義されたメソッドでブロックの実行をラップするために使用されます(セクション Withステートメントコンテキストマネージャーを参照)。 これにより、一般的な try … except … finally の使用パターンをカプセル化して、再利用しやすくなります。
with_stmt ::= "with" with_item ("," with_item)* ":" suite with_item ::= expression ["as" target]
1つの「アイテム」を含む 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
バージョン2.7で変更:複数のコンテキスト式のサポート。
7.6。 関数の定義
関数定義は、ユーザー定義の関数オブジェクトを定義します(セクション標準型階層を参照)。
飾られた ::= decorators (classdef | funcdef) デコレータ ::= decorator+ デコレータ ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE funcdef ::= "def" funcname "(" [parameter_list] ")" ":" suite dotted_name ::= identifier ("." identifier)* parameter_list ::= (defparameter ",")* ( "*" identifier ["," "**" identifier] | "**" identifier | defparameter [","] ) defparameter ::= parameter ["=" expression] サブリスト ::= parameter ("," parameter)* [","] パラメータ ::= identifier | "(" sublist ")" funcname ::= identifier
関数定義は実行可能ステートメントです。 その実行により、現在のローカル名前空間の関数名が関数オブジェクト(関数の実行可能コードのラッパー)にバインドされます。 この関数オブジェクトには、関数が呼び出されたときに使用されるグローバル名前空間として、現在のグローバル名前空間への参照が含まれています。
関数定義は関数本体を実行しません。 これは、関数が呼び出されたときにのみ実行されます。 2
関数定義は、1つ以上のデコレータ式でラップできます。 デコレータ式は、関数が定義されたときに、関数定義を含むスコープで評価されます。 結果は、関数オブジェクトを唯一の引数として呼び出される呼び出し可能である必要があります。 戻り値は、関数オブジェクトではなく関数名にバインドされます。 複数のデコレータがネストされた方法で適用されます。 たとえば、次のコード:
@f1(arg)
@f2
def func(): pass
と同等です:
def func(): pass
func = f1(arg)(f2(func))
1つ以上のトップレベルのパラメーターがパラメーター =
式の形式である場合、関数は「デフォルトのパラメーター値」を持っていると言われます。 デフォルト値のパラメーターの場合、対応する引数を呼び出しから省略できます。その場合、パラメーターのデフォルト値が置き換えられます。 パラメータにデフォルト値がある場合、後続のすべてのパラメータにもデフォルト値が必要です。これは構文上の制限であり、文法では表現されません。
デフォルトのパラメーター値は、関数定義の実行時に評価されます。これは、関数の定義時に式が1回評価され、各呼び出しに同じ「事前計算」値が使用されることを意味します。 これは、デフォルトのパラメータがリストや辞書などの可変オブジェクトである場合を理解するために特に重要です。関数がオブジェクトを変更する場合(例: リストに項目を追加することにより)、デフォルト値は事実上変更されます。 これは一般的に意図されたものではありません。 これを回避する方法は、デフォルトとしてNone
を使用し、関数の本体で明示的にテストすることです。例:
def whats_on_the_telly(penguin=None):
if penguin is None:
penguin = []
penguin.append("property of the zoo")
return penguin
関数呼び出しのセマンティクスについては、呼び出しのセクションで詳しく説明しています。 関数呼び出しは、位置引数、キーワード引数、またはデフォルト値のいずれかから、パラメーターリストに記載されているすべてのパラメーターに常に値を割り当てます。 「*identifier
」という形式が存在する場合は、余分な位置パラメーターを受け取るタプルに初期化され、デフォルトで空のタプルになります。 「**identifier
」という形式が存在する場合は、余分なキーワード引数を受け取る新しい辞書に初期化され、デフォルトで新しい空の辞書になります。
式ですぐに使用できるように、無名関数(名前にバインドされていない関数)を作成することもできます。 これは、セクション Lambdas で説明されているラムダ式を使用します。 ラムダ式は単純化された関数定義の省略形にすぎないことに注意してください。 「 def 」ステートメントで定義された関数は、ラムダ式で定義された関数と同じように、受け渡したり、別の名前に割り当てたりすることができます。 「 def 」形式は、複数のステートメントを実行できるため、実際にはより強力です。
プログラマーのメモ:関数はファーストクラスのオブジェクトです。 関数定義内で実行される「def
」フォームは、返されるか、渡されることができるローカル関数を定義します。 ネストされた関数で使用される自由変数は、defを含む関数のローカル変数にアクセスできます。 詳細については、セクション命名とバインディングを参照してください。
7.7。 クラス定義
クラス定義はクラスオブジェクトを定義します(セクション標準タイプ階層を参照):
classdef ::= "class" classname [inheritance] ":" suite 継承 ::= "(" [expression_list] ")" クラス名 ::= identifier
クラス定義は実行可能なステートメントです。 継承リストが存在する場合は、最初に評価します。 継承リストの各項目は、サブクラス化を可能にするクラスオブジェクトまたはクラスタイプに評価される必要があります。 次に、クラスのスイートは、新しく作成されたローカル名前空間と元のグローバル名前空間を使用して、新しい実行フレームで実行されます(セクション名前付けとバインディングを参照)。 (通常、スイートには関数定義のみが含まれます。)クラスのスイートが実行を終了すると、その実行フレームは破棄されますが、ローカル名前空間は保存されます。 3 次に、基本クラスの継承リストと属性ディクショナリの保存されたローカル名前空間を使用して、クラスオブジェクトが作成されます。 クラス名は、元のローカル名前空間のこのクラスオブジェクトにバインドされます。
プログラマーのメモ:クラス定義で定義されている変数はクラス変数です。 それらはすべてのインスタンスで共有されます。 インスタンス変数を作成するには、self.name = value
を使用してメソッドに設定できます。 クラス変数とインスタンス変数はどちらも「self.name
」という表記でアクセスできます。インスタンス変数は、この方法でアクセスすると、同じ名前のクラス変数を非表示にします。 クラス変数はインスタンス変数のデフォルトとして使用できますが、可変値を使用すると予期しない結果が生じる可能性があります。 新しいスタイルのクラスの場合、記述子を使用して、実装の詳細が異なるインスタンス変数を作成できます。
関数定義と同様に、クラス定義は1つ以上のデコレータ式でラップできます。 デコレータ式の評価ルールは関数の場合と同じです。 結果はクラスオブジェクトである必要があり、クラスオブジェクトはクラス名にバインドされます。
脚注
- 1
- 別の例外を発生させる finally 句がない限り、例外は呼び出しスタックに伝播されます。 その新しい例外により、古い例外が失われます。
- 2
- 関数本体の最初のステートメントとして表示される文字列リテラルは、関数の
__doc__
属性に変換されるため、関数の docstring に変換されます。 - 3
- クラス本体の最初のステートメントとして表示される文字列リテラルは、名前空間の
__doc__
アイテムに変換されるため、クラスの docstring に変換されます。