4. 実行モデル—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.8/reference/executionmodel
移動先:案内検索

4.4。 実行モデル

4.1。 プログラムの構造

Pythonプログラムは、コードブロックから構築されます。 ブロックは、1つの単位として実行されるPythonプログラムテキストの一部です。 ブロックは次のとおりです。モジュール、関数本体、およびクラス定義。 インタラクティブに入力される各コマンドはブロックです。 スクリプトファイル(インタプリタへの標準入力として指定されたファイル、またはインタプリタへのコマンドライン引数として指定されたファイル)は、コードブロックです。 スクリプトコマンド( -c オプションを使用してインタープリターコマンドラインで指定されたコマンド)は、コードブロックです。 組み込み関数 eval()および exec()に渡される文字列引数はコードブロックです。

コードブロックは実行フレームで実行されます。 フレームには(デバッグに使用される)いくつかの管理情報が含まれ、コードブロックの実行が完了した後、実行をどこでどのように続行するかを決定します。


4.2。 ネーミングとバインディング

4.2.1。 名前のバインド

名前はオブジェクトを参照します。 名前は、名前バインディング操作によって導入されます。

次の構成は名前をバインドします:関数への仮パラメーター、 import ステートメント、クラスと関数の定義(これらは定義ブロック内のクラスまたは関数名をバインドします)、および割り当てで発生する場合は識別子であるターゲット、[ X255X] for ループヘッダー、または with ステートメントまたは except 句のasの後。 from ... import *形式のimportステートメントは、アンダースコアで始まる名前を除き、インポートされたモジュールで定義されたすべての名前をバインドします。 このフォームは、モジュールレベルでのみ使用できます。

del ステートメントで発生するターゲットも、この目的にバインドされていると見なされます(ただし、実際のセマンティクスは名前のバインドを解除することです)。

各割り当てまたはインポートステートメントは、クラスまたは関数の定義によって定義されたブロック内、またはモジュールレベル(最上位のコードブロック)で発生します。

名前がブロックにバインドされている場合、 nonlocal または global として宣言されていない限り、その名前はそのブロックのローカル変数です。 名前がモジュールレベルでバインドされている場合、それはグローバル変数です。 (モジュールコードブロックの変数はローカルおよびグローバルです。)変数がコードブロックで使用されているが、そこで定義されていない場合、それは自由変数です。

プログラムテキスト内の名前の各出現は、次の名前解決規則によって確立されたその名前のバインディングを参照します。


4.2.2。 名前の解決

scope は、ブロック内の名前の可視性を定義します。 ローカル変数がブロックで定義されている場合、そのスコープにはそのブロックが含まれます。 定義が関数ブロックで発生する場合、含まれているブロックが名前に異なるバインディングを導入しない限り、スコープは定義ブロック内に含まれているすべてのブロックに拡張されます。

コードブロックで名前が使用されている場合、最も近い囲みスコープを使用して名前が解決されます。 コードブロックに表示されるこのようなすべてのスコープのセットは、ブロックの環境と呼ばれます。

名前がまったく見つからない場合、 NameError 例外が発生します。 現在のスコープが関数スコープであり、名前が使用された時点でまだ値にバインドされていないローカル変数を参照している場合、 UnboundLocalError 例外が発生します。 UnboundLocalError は、 NameError のサブクラスです。

コードブロック内のどこかで名前バインディング操作が発生した場合、ブロック内での名前の使用はすべて、現在のブロックへの参照として扱われます。 これにより、名前がバインドされる前にブロック内で使用されると、エラーが発生する可能性があります。 このルールは微妙です。 Pythonには宣言がなく、名前バインディング操作をコードブロック内のどこでも実行できます。 コードブロックのローカル変数は、ブロックのテキスト全体をスキャンして名前バインディング操作を行うことで判別できます。

global ステートメントがブロック内で発生する場合、ステートメントで指定された名前のすべての使用は、最上位の名前空間でのその名前のバインディングを参照します。 名前は、グローバル名前空間を検索することにより、最上位の名前空間で解決されます。 コードブロックを含むモジュールの名前空間、および組み込みの名前空間、モジュールの名前空間 builtins 。 グローバル名前空間が最初に検索されます。 名前がそこに見つからない場合は、組み込みの名前空間が検索されます。 globalステートメントは、名前のすべての使用の前に置く必要があります。

global ステートメントは、同じブロック内の名前バインディング操作と同じスコープを持っています。 自由変数の最も近い囲みスコープにグローバルステートメントが含まれている場合、自由変数はグローバルとして扱われます。

nonlocal ステートメントにより、対応する名前は、最も近い囲んでいる関数スコープ内の以前にバインドされた変数を参照します。 SyntaxError は、指定された名前がそれを囲む関数スコープに存在しない場合、コンパイル時に発生します。

モジュールの名前空間は、モジュールが最初にインポートされたときに自動的に作成されます。 スクリプトのメインモジュールは常に __ main __ と呼ばれます。

クラス定義ブロックと exec()および eval()への引数は、名前解決のコンテキストでは特別です。 クラス定義は、名前を使用および定義できる実行可能ステートメントです。 これらの参照は、バインドされていないローカル変数がグローバル名前空間で検索されることを除いて、名前解決の通常のルールに従います。 クラス定義の名前空間は、クラスの属性ディクショナリになります。 クラスブロックで定義されている名前のスコープは、クラスブロックに限定されています。 メソッドのコードブロックには拡張されません。これには、関数スコープを使用して実装されるため、内包表記とジェネレーター式が含まれます。 これは、以下が失敗することを意味します。

class A:
    a = 42
    b = list(a + i for i in range(10))

4.2.3。 ビルトインと制限付き実行

コードブロックの実行に関連付けられている組み込みの名前空間は、実際には、グローバル名前空間で__builtins__という名前を検索することで見つかります。 これは辞書またはモジュールである必要があります(後者の場合、モジュールの辞書が使用されます)。 デフォルトでは、 __ main __ モジュールの場合、__builtins__は組み込みモジュール builtins です。 他のモジュールの場合、__builtins__builtins モジュール自体の辞書のエイリアスです。


4.2.4。 動的機能との相互作用

自由変数の名前解決は、コンパイル時ではなく、実行時に行われます。 これは、次のコードが42を出力することを意味します。

i = 10
def f():
    print(i)
i = 42
f()

eval()および exec()関数は、名前を解決するための完全な環境にアクセスできません。 名前は、呼び出し元のローカルおよびグローバル名前空間で解決される場合があります。 自由変数は、最も近い囲んでいる名前空間ではなく、グローバル名前空間で解決されます。 1 exec()および eval()関数には、グローバルおよびローカル名前空間をオーバーライドするオプションの引数があります。 名前空間が1つだけ指定されている場合は、両方に使用されます。


4.3。 例外

例外は、エラーやその他の例外的な状態を処理するために、コードブロックの通常の制御フローから抜け出す手段です。 例外は、エラーが検出された時点での発生です。 周囲のコードブロック、またはエラーが発生したコードブロックを直接または間接的に呼び出したコードブロックによって処理される可能性があります。

Pythonインタープリターは、実行時エラー(ゼロ除算など)を検出すると例外を発生させます。 Pythonプログラムは、 raise ステートメントを使用して明示的に例外を発生させることもできます。 例外ハンドラーは、 tryexcept ステートメントで指定されます。 このようなステートメントの finally 句を使用して、例外を処理しないクリーンアップコードを指定できますが、前のコードで例外が発生したかどうかに関係なく実行されます。

Pythonはエラー処理の「終了」モデルを使用します。例外ハンドラーは何が起こったのかを見つけて外部レベルで実行を続行できますが、エラーの原因を修復して失敗した操作を再試行することはできません(問題のある部分を再入力する場合を除く)上からのコードの)。

例外がまったく処理されない場合、インタプリタはプログラムの実行を終了するか、インタラクティブなメインループに戻ります。 いずれの場合も、例外が SystemExit の場合を除いて、スタックトレースバックを出力します。

例外はクラスインスタンスによって識別されます。 exception 句は、インスタンスのクラスに応じて選択されます。インスタンスのクラスまたはその基本クラスを参照する必要があります。 インスタンスはハンドラーが受け取ることができ、例外条件に関する追加情報を運ぶことができます。

ノート

例外メッセージはPythonAPIの一部ではありません。 それらの内容は、警告なしにPythonのバージョンごとに変更される可能性があるため、複数のバージョンのインタープリターで実行されるコードに依存しないでください。


セクション tryステートメントtry ステートメントおよびセクション raiseステートメントraise ステートメントの説明も参照してください。

脚注

1
この制限は、これらの操作によって実行されるコードが、モジュールのコンパイル時に使用できないために発生します。