8.8。 複合ステートメント
複合ステートメントには、他のステートメント(のグループ)が含まれます。 それらは、何らかの方法でそれらの他のステートメントの実行に影響を与えるか、または制御します。 一般に、複合ステートメントは複数の行にまたがりますが、単純な化身では、複合ステートメント全体が1行に含まれる場合があります。
if 、 while 、および for ステートメントは、従来の制御フロー構造を実装します。 try は、ステートメントのグループの例外ハンドラーやクリーンアップコードを指定し、 with ステートメントは、コードブロックの周囲で初期化および終了コードを実行できます。 関数とクラスの定義も構文的に複合ステートメントです。
複合ステートメントは、1つ以上の「句」で構成されます。 句は、ヘッダーと「スイート」で構成されます。 特定の複合ステートメントの句ヘッダーはすべて同じインデントレベルにあります。 各句ヘッダーは、一意に識別するキーワードで始まり、コロンで終わります。 スイートは、句によって制御されるステートメントのグループです。 スイートは、ヘッダーのコロンに続く、ヘッダーと同じ行にある1つ以上のセミコロンで区切られた単純なステートメントにすることも、後続の行にある1つ以上のインデントされたステートメントにすることもできます。 ネストされた複合ステートメントを含めることができるのは、後者の形式のスイートのみです。 以下は違法です。これは主に、後続の else 句がどの if 句に属するかが明確でないためです。
また、このコンテキストではセミコロンがコロンよりも緊密にバインドされるため、次の例では、 print()呼び出しがすべて実行されるか、まったく実行されないことに注意してください。
要約:
Compound_stmt ::= if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | async_with_stmt | async_for_stmt | async_funcdef スイート ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT ステートメント ::= stmt_list NEWLINE | compound_stmt stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
ステートメントは常にNEWLINE
で終わり、その後にDEDENT
が続く可能性があることに注意してください。 また、オプションの継続句は常にステートメントを開始できないキーワードで始まるため、あいまいさはありません(Pythonでは、ネストされた if ステートメントを要求することで「ぶら下がり else 」の問題が解決されます)インデントされます)。
次のセクションの文法規則のフォーマットでは、わかりやすくするために各句を別々の行に配置しています。
8.1。 NSif 声明
if ステートメントは、条件付き実行に使用されます。
if_stmt ::= "if" assignment_expression ":" suite ("elif" assignment_expression ":" suite)* ["else" ":" suite]
1つがtrueであることが判明するまで、式を1つずつ評価することにより、スイートの1つを正確に選択します(trueとfalseの定義については、セクションブール演算を参照してください)。 次に、そのスイートが実行されます( if ステートメントの他の部分は実行または評価されません)。 すべての式がfalseの場合、 else 句のスイートが存在する場合は実行されます。
8.2。 NSwhile 声明
while ステートメントは、式が真である限り、繰り返し実行するために使用されます。
while_stmt ::= "while" assignment_expression ":" suite ["else" ":" suite]
これは式を繰り返しテストし、それがtrueの場合、最初のスイートを実行します。 式がfalseの場合(初めてテストされる場合があります)、else
句のスイートが存在する場合は実行され、ループが終了します。
最初のスイートで実行された break ステートメントは、else
句のスイートを実行せずにループを終了します。 最初のスイートで実行された continue ステートメントは、スイートの残りの部分をスキップして、式のテストに戻ります。
8.3。 NSfor 声明
for ステートメントは、シーケンスの要素(文字列、タプル、リストなど)またはその他の反復可能なオブジェクトを反復処理するために使用されます。
for_stmt ::= "for" target_list "in" expression_list ":" suite ["else" ":" suite]
式リストは1回評価されます。 反復可能なオブジェクトを生成する必要があります。 expression_list
の結果に対してイテレータが作成されます。 次に、スイートは、イテレータによって提供されたアイテムごとに、イテレータによって返された順序で1回実行されます。 次に、各アイテムは、割り当ての標準ルールを使用してターゲットリストに割り当てられ(割り当てステートメントを参照)、スイートが実行されます。 アイテムが使い果たされると(シーケンスが空になるか、イテレータが StopIteration 例外を発生させるとすぐに)、else
句のスイートが実行され、ループが発生します。終了します。
最初のスイートで実行された break ステートメントは、else
句のスイートを実行せずにループを終了します。 最初のスイートで実行された continue ステートメントは、スイートの残りの部分をスキップして次のアイテムに進みます。次のアイテムがない場合は、else
句に進みます。
forループは、ターゲットリスト内の変数に割り当てを行います。 これにより、forループのスイートで行われたものを含め、これらの変数への以前のすべての割り当てが上書きされます。
ターゲットリスト内の名前は、ループの終了時に削除されませんが、シーケンスが空の場合、ループによってまったく割り当てられていません。 ヒント:組み込み関数 range()は、Pascalのfor i := a to b do
の効果をエミュレートするのに適した整数のイテレーターを返します。 たとえば、list(range(3))
はリスト[0, 1, 2]
を返します。
ノート
シーケンスがループによって変更されている場合は微妙です(これは、可変シーケンスでのみ発生する可能性があります。 リスト)。 内部カウンターは、次に使用されるアイテムを追跡するために使用され、これは反復ごとにインクリメントされます。 このカウンターがシーケンスの長さに達すると、ループは終了します。 これは、スイートがシーケンスから現在の(または前の)アイテムを削除した場合、次のアイテムはスキップされることを意味します(すでに処理された現在のアイテムのインデックスを取得するため)。 同様に、スイートが現在のアイテムの前にシーケンス内のアイテムを挿入した場合、現在のアイテムは次回ループを介して再度処理されます。 これは厄介なバグにつながる可能性があり、シーケンス全体のスライスを使用して一時的なコピーを作成することで回避できます。
8.4。 NStry 声明
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
exception 句は、1つ以上の例外ハンドラーを指定します。 try 句で例外が発生しない場合、例外ハンドラーは実行されません。 try
スイートで例外が発生すると、例外ハンドラーの検索が開始されます。 この検索では、例外に一致するものが見つかるまで、except句が順番に検査されます。 式のないexcept句が存在する場合は、最後にする必要があります。 すべての例外に一致します。 式を含むexcept句の場合、その式が評価され、結果のオブジェクトが例外と「互換性がある」場合、句は例外と一致します。 オブジェクトが例外オブジェクトのクラスまたは基本クラスである場合、あるいは例外オブジェクトのクラスまたは基本クラスである項目を含むタプルである場合、そのオブジェクトは例外と互換性があります。
例外に一致するexcept句がない場合、例外ハンドラーの検索は、周囲のコードと呼び出しスタックで続行されます。 1
例外句のヘッダーにある式の評価で例外が発生した場合、ハンドラーの元の検索はキャンセルされ、周囲のコードと呼び出しスタックで新しい例外の検索が開始されます(全体として扱われます)。 try ステートメントで例外が発生しました)。
一致するexcept句が見つかると、そのexcept句のas
キーワードの後に指定されたターゲットに例外が割り当てられ、存在する場合は、except句のスイートが実行されます。 句を除くすべての句には、実行可能ブロックが必要です。 このブロックの終わりに達すると、tryステートメント全体の後で通常どおり実行が続行されます。 (これは、同じ例外に対して2つのネストされたハンドラーが存在し、例外が内部ハンドラーのtry句で発生した場合、外部ハンドラーは例外を処理しないことを意味します。)
as target
を使用して例外が割り当てられた場合、例外句の最後で例外がクリアされます。 これはまるで
に翻訳されました
つまり、except句の後で例外を参照できるようにするには、例外を別の名前に割り当てる必要があります。 例外は、トレースバックがアタッチされた状態でスタックフレームとの参照サイクルを形成し、次のガベージコレクションが発生するまでそのフレーム内のすべてのローカルを存続させるためにクリアされます。
例外句のスイートが実行される前に、例外に関する詳細が sys モジュールに格納され、 sys.exc_info()を介してアクセスできます。 sys.exc_info()は、例外クラス、例外インスタンス、およびプログラム内のポイントを識別するトレースバックオブジェクト(セクション標準タイプ階層を参照)で構成される3タプルを返します。例外が発生しました。 sys.exc_info()の値は、例外を処理した関数から戻るときに、(呼び出し前の)以前の値に復元されます。
オプションのelse
句は、制御フローが try スイートを離れ、例外が発生せず、 return 、 Continue 、または break ステートメントが実行されました。 else
句の例外は、先行する exception 句では処理されません。
最終的にが存在する場合は、「クリーンアップ」ハンドラーを指定します。 try 句が実行されます。これには、句とelse
句を除くすべてのが含まれます。 いずれかの句で例外が発生し、処理されない場合、例外は一時的に保存されます。 finally
句が実行されます。 保存された例外がある場合は、finally
句の最後で再発生します。 finally
句で別の例外が発生した場合、保存された例外が新しい例外のコンテキストとして設定されます。 finally
句が return 、 break または continue ステートメントを実行すると、保存された例外は破棄されます。
finally 句の実行中は、プログラムは例外情報を利用できません。
return 、 break または continue ステートメントが、try
…finally
ステートメント、 finally 句も「途中で」実行されます。
関数の戻り値は、最後に実行された return ステートメントによって決定されます。 finally 句は常に実行されるため、finally
句で実行されるreturn
ステートメントは常に最後に実行されます。
例外に関する追加情報はセクション Exceptions にあり、 raise ステートメントを使用して例外を生成する方法に関する情報はセクション raiseステートメントにあります。
8.5。 NSwith 声明
with ステートメントは、コンテキストマネージャーによって定義されたメソッドでブロックの実行をラップするために使用されます(セクション Withステートメントコンテキストマネージャーを参照)。 これにより、一般的な try … except … finally の使用パターンをカプセル化して、再利用しやすくなります。
with_stmt ::= "with" with_item ("," with_item)* ":" suite with_item ::= expression ["as" target]
1つの「アイテム」を含む with ステートメントの実行は、次のように進行します。
コンテキスト式(
with_item
で指定された式)が評価され、コンテキストマネージャーが取得されます。コンテキストマネージャの
__enter__()
は、後で使用するためにロードされます。コンテキストマネージャの
__exit__()
は、後で使用するためにロードされます。コンテキストマネージャの
__enter__()
メソッドが呼び出されます。with ステートメントにターゲットが含まれている場合、
__enter__()
からの戻り値がターゲットに割り当てられます。ノート
with ステートメントは、
__enter__()
メソッドがエラーなしで返される場合、__exit__()
が常に呼び出されることを保証します。 したがって、ターゲットリストへの割り当て中にエラーが発生した場合、スイート内で発生したエラーと同じように扱われます。 以下のステップ6を参照してください。スイートが実行されます。
コンテキストマネージャの
__exit__()
メソッドが呼び出されます。 例外によってスイートが終了した場合、そのタイプ、値、およびトレースバックが引数として__exit__()
に渡されます。 それ以外の場合は、3つの None 引数が指定されます。例外が原因でスイートが終了し、
__exit__()
メソッドからの戻り値がfalseの場合、例外が再発生します。 戻り値がtrueの場合、例外は抑制され、 with ステートメントに続くステートメントから実行が続行されます。例外以外の理由でスイートが終了した場合、
__exit__()
からの戻り値は無視され、実行は、実行された種類の終了の通常の場所で続行されます。
次のコード:
意味的には次のものと同等です。
複数のアイテムがある場合、コンテキストマネージャーは、複数の with ステートメントがネストされているかのように処理されます。
意味的には次のものと同等です。
バージョン3.1で変更:複数のコンテキスト式のサポート。
8.6。 関数の定義
関数定義は、ユーザー定義の関数オブジェクトを定義します(セクション標準型階層を参照)。
funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite デコレータ ::= decorator+ デコレータ ::= "@" assignment_expression NEWLINE parameter_list ::= defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]] | parameter_list_no_posonly parameter_list_no_posonly ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]] | parameter_list_starargs parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]] | "**" parameter [","] パラメーター ::= identifier [":" expression] defparameter ::= parameter ["=" expression] funcname ::= identifier
関数定義は実行可能ステートメントです。 その実行により、現在のローカル名前空間の関数名が関数オブジェクト(関数の実行可能コードのラッパー)にバインドされます。 この関数オブジェクトには、関数が呼び出されたときに使用されるグローバル名前空間として、現在のグローバル名前空間への参照が含まれています。
関数定義は関数本体を実行しません。 これは、関数が呼び出されたときにのみ実行されます。 2
関数定義は、1つ以上のデコレータ式でラップできます。 デコレータ式は、関数が定義されたときに、関数定義を含むスコープで評価されます。 結果は、関数オブジェクトを唯一の引数として呼び出される呼び出し可能である必要があります。 戻り値は、関数オブジェクトではなく関数名にバインドされます。 複数のデコレータがネストされた方法で適用されます。 たとえば、次のコード
とほぼ同等です
ただし、元の関数は一時的にfunc
という名前にバインドされていません。
バージョン3.9で変更:関数は有効なassignment_expression
で装飾できます。 以前は、文法ははるかに制限的でした。 詳細については、 PEP 614 を参照してください。
1つ以上のパラメータがパラメータ =
式の形式である場合、関数は「デフォルトのパラメータ値」を持っていると言われます。 デフォルト値のパラメーターの場合、対応する引数を呼び出しから省略できます。その場合、パラメーターのデフォルト値が置き換えられます。 パラメータにデフォルト値がある場合、「*
」までの後続のすべてのパラメータにもデフォルト値が必要です。これは、文法で表現されていない構文上の制限です。
デフォルトのパラメーター値は、関数定義の実行時に左から右に評価されます。これは、関数が定義されたときに式が1回評価され、同じ「事前計算」値がに使用されることを意味します。各呼び出し。 これは、デフォルトのパラメータがリストや辞書などの可変オブジェクトである場合を理解するために特に重要です。関数がオブジェクトを変更する場合(例: アイテムをリストに追加することにより)、デフォルト値は事実上変更されます。 これは一般的に意図されたものではありません。 これを回避する方法は、デフォルトとしてNone
を使用し、関数の本体で明示的にテストすることです。例:
関数呼び出しのセマンティクスについては、呼び出しのセクションで詳しく説明しています。 関数呼び出しは、位置引数、キーワード引数、またはデフォルト値のいずれかから、パラメーターリストに記載されているすべてのパラメーターに常に値を割り当てます。 「*identifier
」という形式が存在する場合は、余分な位置パラメーターを受け取るタプルに初期化され、デフォルトで空のタプルになります。 「**identifier
」という形式が存在する場合、過剰なキーワード引数を受け取る新しい順序付きマッピングに初期化され、デフォルトで同じタイプの新しい空のマッピングになります。 「*
」または「*identifier
」の後のパラメーターはキーワードのみのパラメーターであり、キーワード引数によってのみ渡すことができます。 「/
」の前のパラメーターは位置のみのパラメーターであり、位置引数によってのみ渡すことができます。
バージョン3.8で変更: /
関数パラメーター構文を使用して、位置のみのパラメーターを示すことができます。 詳細については、 PEP 570 を参照してください。
パラメータには、パラメータ名の後に「: expression
」の形式の注釈が付いている場合があります。 *identifier
または**identifier
の形式のパラメーターであっても、任意のパラメーターに注釈を付けることができます。 関数には、パラメータリストの後に「-> expression
」という形式の「return」注釈が付いている場合があります。 これらのアノテーションは、任意の有効なPython式にすることができます。 アノテーションが存在しても、関数のセマンティクスは変更されません。 注釈値は、関数オブジェクトの__annotations__
属性のパラメーター名でキー設定されたディクショナリの値として使用できます。 __ future __ からのannotations
インポートが使用される場合、注釈は実行時に文字列として保持されるため、評価を延期できます。 それ以外の場合は、関数定義の実行時に評価されます。 この場合、注釈はソースコードに表示される順序とは異なる順序で評価される可能性があります。
式ですぐに使用できるように、無名関数(名前にバインドされていない関数)を作成することもできます。 これは、セクション Lambdas で説明されているラムダ式を使用します。 ラムダ式は単純化された関数定義の省略形にすぎないことに注意してください。 「 def 」ステートメントで定義された関数は、ラムダ式で定義された関数と同じように、受け渡したり、別の名前に割り当てたりすることができます。 「def
」フォームは、複数のステートメントと注釈を実行できるため、実際にはより強力です。
プログラマーのメモ:関数はファーストクラスのオブジェクトです。 関数定義内で実行される「def
」ステートメントは、返されるか、渡されることができるローカル関数を定義します。 ネストされた関数で使用される自由変数は、defを含む関数のローカル変数にアクセスできます。 詳細については、セクション命名とバインディングを参照してください。
8.7。 クラス定義
クラス定義はクラスオブジェクトを定義します(セクション標準タイプ階層を参照):
classdef ::= [decorators] "class" classname [inheritance] ":" suite 継承 ::= "(" [argument_list] ")" クラス名 ::= identifier
クラス定義は実行可能なステートメントです。 継承リストは通常、基本クラスのリストを提供します(より高度な使用法については、メタクラスを参照)。したがって、リスト内の各項目は、サブクラス化を許可するクラスオブジェクトに評価される必要があります。 継承リストのないクラスは、デフォルトで、基本クラス object から継承します。 したがって、
と同等です
次に、クラスのスイートは、新しく作成されたローカル名前空間と元のグローバル名前空間を使用して、新しい実行フレームで実行されます(名前空間とバインディングを参照)。 (通常、スイートには主に関数定義が含まれています。)クラスのスイートが実行を終了すると、その実行フレームは破棄されますが、ローカル名前空間は保存されます。 3 次に、基本クラスの継承リストと属性ディクショナリの保存されたローカル名前空間を使用して、クラスオブジェクトが作成されます。 クラス名は、元のローカル名前空間のこのクラスオブジェクトにバインドされます。
クラス本体で属性が定義される順序は、新しいクラスの__dict__
で保持されます。 これは、クラスが作成された直後、および定義構文を使用して定義されたクラスに対してのみ信頼できることに注意してください。
クラスの作成は、 metaclasses を使用して大幅にカスタマイズできます。
クラスも装飾できます。関数を装飾するときと同じように、
とほぼ同等です
デコレータ式の評価ルールは、関数デコレータの場合と同じです。 結果はクラス名にバインドされます。
バージョン3.9で変更:クラスは任意の有効なassignment_expression
で装飾できます。 以前は、文法ははるかに制限的でした。 詳細については、 PEP 614 を参照してください。
プログラマーのメモ:クラス定義で定義されている変数はクラス属性です。 それらはインスタンスによって共有されます。 インスタンス属性は、self.name = value
のメソッドで設定できます。 クラス属性とインスタンス属性はどちらも「self.name
」という表記でアクセスできます。インスタンス属性は、この方法でアクセスすると、同じ名前のクラス属性を非表示にします。 クラス属性はインスタンス属性のデフォルトとして使用できますが、可変値を使用すると予期しない結果が生じる可能性があります。 記述子を使用して、実装の詳細が異なるインスタンス変数を作成できます。
8.8。 コルーチン
バージョン3.5の新機能。
8.8.1。 コルーチン関数の定義
async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite
Pythonコルーチンの実行は、多くの時点で一時停止および再開できます(コルーチンを参照)。 コルーチン関数の本体内では、await
およびasync
識別子が予約済みキーワードになります。 await 式、 async for 、および async with は、コルーチン関数本体でのみ使用できます。
async def
構文で定義された関数は、await
またはasync
キーワードが含まれていない場合でも、常にコルーチン関数です。
コルーチン関数の本体内でyield from
式を使用するのは SyntaxError です。
コルーチン関数の例:
8.8.2。 NSasync for 声明
async_for_stmt ::= "async" for_stmt
非同期イテレータは、非同期イテレータを直接返す__aiter__
メソッドを提供します。このメソッドは、__anext__
メソッドで非同期コードを呼び出すことができます。
async for
ステートメントを使用すると、非同期反復可能オブジェクトを簡単に反復できます。
次のコード:
意味的には次のものと同等です。
詳細については、__aiter__()
および__anext__()
も参照してください。
コルーチン関数の本体の外でasync for
ステートメントを使用するのは SyntaxError です。
8.8.3。 NSasync with 声明
async_with_stmt ::= "async" with_stmt
非同期コンテキストマネージャーは、 enter および exit メソッドで実行を一時停止できるコンテキストマネージャーです。
次のコード:
意味的には次のものと同等です。
詳細については、__aenter__()
および__aexit__()
も参照してください。
コルーチン関数の本体の外でasync with
ステートメントを使用するのは SyntaxError です。
脚注
- 1
- 別の例外を発生させる finally 句がない限り、例外は呼び出しスタックに伝播されます。 その新しい例外により、古い例外が失われます。
- 2
- 関数本体の最初のステートメントとして表示される文字列リテラルは、関数の
__doc__
属性に変換されるため、関数の docstring に変換されます。 - 3
- クラス本体の最初のステートメントとして表示される文字列リテラルは、名前空間の
__doc__
アイテムに変換されるため、クラスの docstring に変換されます。