
.. _execmodel:

**********
実行モデル
**********

.. index:: single: execution model


.. _naming:

名前づけと束縛 (naming and binding)
===================================

.. index::
   pair: code; block
   single: namespace
   single: scope

.. index::
   single: name
   pair: binding; name

:dfn:`名前 (name)` とは、オブジェクトを参照するものを指します。名前への束縛 (name binding) 操作を行うと、
名前を導入できます。プログラムテキスト中に名前が出現するたびに、その名前が使われている最も内側の関数ブロック中で作成された :dfn:`束縛
(binding)` を使って名前の参照が行われます。

.. index:: single: block

ブロック(:dfn:`block`)は、Python のプログラムテキストからなる断片で、一つの実行単位となるものです。
モジュール、関数本体、そしてクラス定義はブロックです。また、対話的に入力された個々のコマンドもブロックです。スクリプトファイル
(インタプリタに標準入力として与えたり、コマンドラインの第一引数として指定したファイル) は、コードブロックです。スクリプトコマンド
(インタプリタのコマンドライン上で '**-c**' オプションを使って指定したコマンド) もコードブロックです。組み込み関数 :func:`eval` や
:keyword:`exec` 文に渡した文字列もコードブロックになります。組み込み関数 :func:`input` から読み取られ、評価される
式もまた、コードブロックです。

.. index:: pair: execution; frame

コードブロックは、実行フレーム(:dfn:`execution frame`) 上で実行されます。実行フレームには、 (デバッグに使われる)
管理情報が収められています。また、現在のコードブロックの実行が完了した際に、どのようにプログラムの実行を継続するかを決定しています。

.. index:: single: scope

スコープ(:dfn:`scope`)は、ある名前があるブロック内で参照できるかどうかを決めます。
ローカル変数があるブロック内で定義されている場合、変数のスコープはそのブロックを含みます。
関数ブロック内で名前の定義を行った場合、その名前に対して別の束縛を行っているブロックを除いた、
関数内の全てのブロックを含むようにスコープが拡張されます。
クラス内で定義された名前のスコープは、クラスのブロック内に制限されます;
スコープがメソッドのコードブロックを含むよう拡張されることはありません。
-- ジェネレータ式も関数スコープを利用して実装されているのでスコープの拡張範囲外です。
つまり、次のようなコードは失敗します。 ::

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

.. index:: single: environment

ある名前がコードブロック内で使われると、その名前を最も近傍から囲うようなスコープ (最内スコープ: nearest enclosing scope)
を使って束縛の解決を行います。こうしたスコープからなる、あるコードブロック内で参照できるスコープ全ての集合は、ブロックの
環境(:dfn:`environment`)と呼ばれます。

.. index:: pair: free; variable

ある名前がブロック内で束縛されている場合、名前はそのブロックにおけるローカル変数 (local variable) です。
ある名前がモジュールレベルで束縛されている場合、名前はグローバル変数 (global variable) です。
(モジュールコードブロックの変数は、ローカル変数でもあるし、グローバル変数でもあります。) ある変数がコードブロック内で使われているが、そのブロックでは定義
されていない場合、変数は自由変数(:dfn:`free variable`)です。

.. index::
   single: NameError (built-in exception)
   single: UnboundLocalError

ある名前の定義がどこにもない場合、 :exc:`NameError` 例外が送出されます。名前がまだ束縛されていないローカルな変数を参照
した場合、 :exc:`UnboundLocalError`  例外が送出されます。 :exc:`UnboundLocalError` は、
:exc:`NameError` のサブクラスです。

.. index:: statement: from

名前への束縛は、以下の文構成(construct)で行われます: 関数の仮引数 (formal parameter) 指定、 :keyword:`import`
文、クラスや関数の定義 (定義を行ったブロック中で、クラスや関数名の束縛が行われます)、
代入時に代入対象が識別子である場合、 :keyword:`for` ループのヘッダ、 :keyword:`except` 文ヘッダの
第二要素、 :keyword:`with` 文の中の :keyword:`as` の後ろ。

"``from...import *``" 形式の import 文は、 import しようとするモジュール内で定義されている名前について、
アンダースコアから始まっている名前以外の全てを束縛します。
この形式は、モジュールレベルでしか使うことができません。

:keyword:`del` 文で指定された対象は、(:keyword:`del` の意味付けは、実際は名前の解放 (unbind) ですが)
文の目的上、束縛済みのものとみなされます。外側のスコープで参照されている名前の解放は、不正な操作になります; コンパイラは
:exc:`SyntaxError` を報告するでしょう。

代入文や import 文はいずれも、クラスや関数定義、モジュールレベル (トップレベルのコードブロック) 内で起こります。

ある名前束縛操作がコードブロック内のどこかにある場合、ブロック内でその名前を使うと、全て現在のブロックで束縛されている名前を
指すものとみなされます。このため、ある名前が束縛される前にブロック内で使われるとエラーを引き起こす可能性があります。

この規則はやや微妙です。Python には宣言文がなく、コードブロックのどこで名前束縛操作を行ってもかまいません。あるコードブロックにおけるローカル変数は、
ブロック全体から名前束縛操作が行われている部分を走査して決定します。

global 文で指定された名前がブロック内にある場合、その名前は常にトップレベルの名前空間で束縛された名前を参照します。
それらの名前はグローバル名前空間、すなわちコードブロックが収められているモジュールの名前空間とモジュール名 :mod:`__builtin__`
で表される組み込み名前空間、を検索することによって、トップレベルの名前空間で解決されます。グローバル名前空間は、常に最初に検索
されます。名前がグローバル名前空間中に見つからない場合、組み込み名前空間が検索されます。global 文は、その名前が使われている全て
の文に先立って記述されていなければなりません。

.. index:: pair: restricted; execution

あるコードブロックの実行時に関連付けられる組み込み名前空間は、実際にはコードブロックのグローバル名前空間内に入っている名前 ``__builtins__``
を参照する形になっています; ``__builtins__``  は辞書かモジュール (後者の場合にはモジュールの辞書が使われます)
でなければなりません。デフォルトで ``__main__`` モジュール中においては、 ``__builtins__`` は組み込みモジュール
:mod:`__builtin__` です (注意: 's' なし)；それ以外のモジュールでは、 ``__builtins__`` は
:mod:`__builtin__` モジュールそれ自身の辞書のエイリアスです。 ``__builtins__`` はユーザが作成した辞書を
設定して、弱い形態の制限実行  を作成することが可能です。

.. note::

   ユーザは ``__builtins__`` に触れるべきではありません；これはくれぐれも実装の詳細であるのです。組み込みの名前空間の中の値を
   オーバーライドしたいユーザは、 :mod:`__builtin__` ('s'はありません)  モジュールを :keyword:`import`
   して、その属性を好きに変更するべきです。

.. index:: module: __main__

あるモジュールの名前空間は、そのモジュールが最初に import された時に自動的に作成されます。スクリプトの主モジュール (main module)は常に
:mod:`__main__` と呼ばれます。

グローバル文は、同じブロックの束縛操作と同じスコープを持ちます。ある自由変数の最内スコープに global 文がある場合、その自由変数は
グローバル変数とみなされます。

クラス定義は一つの実行文で、名前の使用や定義を行います。クラス定義への参照は、通常の名前解決規則に従います。
クラス定義の名前空間は、そのクラスの属性辞書になります。クラスのスコープで定義された名前は、メソッドからは見えません。


.. _dynamic-features:

動的な機能とのやりとり
----------------------

自由変数の入った入れ子スコープ (nested scope) を併用すると、 Python の文が不正な文になる場合がいくつかあります。

ある変数がスコープの外側から参照された場合、その名前に対する削除操作は不正になります。この場合、コンパイル時にエラーが報告されることになります。

ワイルドカード形式の import 文  --- ``import *`` ---  を関数内で使った場合や、関数が自由変数を含んでいたり、自由変数
を伴う入れ子ブロックである場合、コンパイラは :exc:`SyntaxError` を送出します。

:keyword:`exec` が関数内で使われており、関数が自由変数を含んでいたり、自由変数を伴う入れ子ブロックである場合、 :keyword:`exec`
に明示的にローカル名前空間を指定しないかぎりコンパイラは SyntaxError を送出します。 (別の言い方をすれば、 ``exec obj``
は不正になることがあり、 ``exec obj in ns`` はならない、ということです。)

:func:`eval` 、 :func:`execfile` 、および :func:`input` 関数、そして :keyword:`exec`
文は、名前の解決を行う際に、現在の環境に対して完全にアクセスできるわけではありません。名前が呼び出し側の
ローカル名前空間やグローバル名前空間から解決されることはあります。自由変数は最内名前空間ではなく、グローバル名前空間から解決されます。  [#]_

:keyword:`exec` 文と、関数 :func:`eval` および :func:`execfile` にはオプションの引数があり、グローバルおよび
ローカル名前空間をオーバライドできます。名前空間を一つしか指定しなければ、両方の名前空間として使われます。


.. _exceptions:

例外
====

.. index:: single: exception

.. index::
   single: raise an exception
   single: handle an exception
   single: exception handler
   single: errors
   single: error handling

例外とは、コードブロックの通常の制御フローを中断して、エラーやその他の例外的な状況を処理できるようにするための手段です。例外はエラーが検出された時点で
*送出 (raise)* されます; 例外は、エラーが発生部の周辺のコードブロックか、エラーが発生した
コードブロック直接または間接的に呼び出しているコードブロックで *処理 (handle)* することができます。

Python インタプリタは、ランタイムエラー (ゼロによる除算など) が検出されると例外を送出します。Python
プログラムから、 :keyword:`raise` 文を使って明示的に例外を送出することもできます。例外ハンドラ (exception handler) は、
:keyword:`try` ... :keyword:`except` 文で指定することができます。
:keyword:`try` 文の :keyword:`finally` 節を使うとクリーンアップコード (cleanup code) を指定できます。
このコードは例外は処理しませんが、先行するコードブロックで例外が起きても起きなくても実行されます。

.. index:: single: termination model

Python は、エラー処理に "プログラムの終了 (termination)"  モデルを用いています: 例外ハンドラは、
プログラムに何が発生したかを把握することができ、ハンドラの外側のレベルに処理を継続することはできますが、(問題のあったコード部分を
最初から実行しなおすのでない限り) エラーの原因を修復したり、実行に失敗した操作をやり直すことはできません。

.. index:: single: SystemExit (built-in exception)

例外が全く処理されない場合、インタプリタはプログラムの実行を終了させるか、対話メインループに処理を戻します。どちらの場合も、例外が
:exc:`SystemExit` でない限りバックトレース (backtrace) を出力します。

例外は、クラスインスタンスによって識別されます。 :keyword:`except` 節はインスタンスのクラスにもとづいて選択されます：
これはインスタンスのクラスか、そのベースクラスを参照します。このインスタンスはハンドラによって受け取られ、例外条件に関する追加情報を伝えることができます。

例外は文字列 (strings) によっても識別することができ、このような場合には :keyword:`except`
節はオブジェクトの同一性によって選択されます。任意の値をハンドラに渡される識別文字列に伴って送出することができます。

.. warning::

   例外に対するメッセージは、Python API 仕様には含まれていません。メッセージの内容は、ある Python のバージョンから次のバージョンに
   なるときに、警告なしに変更される可能性があります。したがって、複数バージョンのインタプリタで動作するようなコードにおいては、
   例外メッセージの内容に依存した記述をすべきではありません。

:keyword:`try` 文については、 :ref:`try` 節、 :keyword:`raise` 文については  :ref:`raise`
節も参照してください。

.. rubric:: Footnotes

.. [#] この制限は、上記の操作によって実行されるコードが、モジュールをコンパイルしたときには利用できないために起こります。

