この記事では、滞在が調整されたような概念は、フォローアップが閉鎖関連のブログを整理しますで、深詳細な閉鎖のための道を開く理解することです。
1.ケーススタディ
閉鎖関連する概念の仕上げ工程では、それはしばしばUnboundLocalErrorとNameErrorに非常に混乱することができます最初に遭遇した2つのエラーが発見され、このようなエラーは起動できません。
1.1ケースI:
DEF outer_func():
loc_var = "ローカル変数"
DEF inner_func():
loc_var + = "内側FUNCで"
戻りloc_varの
戻りinner_func
clo_func = outer_func()
clo_func()
エラーメッセージ:
トレースバック(最新の呼び出しの最後): ファイル" G:\プロジェクトファイル\ Pythonのテスト\ Main.py "、行238、で、<モジュール> clo_func() ファイル" G:\プロジェクトファイル\ Pythonのテスト\ Main.py "、ライン233 におけるinner_func loc_var + = 「内側FUNCで」 ローカル変数:UnboundLocalError 「loc_var 」割当前に参照さ
1.2ケースII:
1 デフ get_select_desc(名前、フラグ、is_format = TRUE): 2 かのフラグ: 3 SEL_RES = ' =%sの選択名前を行います'%の名前を 4 リターン SEL_RES 場合 is_format 他の名前 5 6 get_select_desc(' エラー'、FALSE、TRUE)
エラーメッセージ:
トレースバック(最新の呼び出しの最後): ファイル" G:\プロジェクトファイル\ Pythonのテスト\ Main.py "、行247、で、<モジュール> get_select_desc(' エラー' 、FALSE、TRUE) ファイル" G:\プロジェクトファイル\パイソンテスト\ Main.py "、行245、中get_select_desc リターン SEL_RES 場合 is_format 他の名前 UnboundLocalError:ローカル変数『SEL_RESは、』割り当ての前に参照さ
1.3ケース3:
DEF outer_func(out_flag):
もしout_flag:
loc_var1 = 'フラグと、ローカル変数'
:他
loc_var2 = 'フラグなしでローカル変数'
(in_flag)inner_func DEF:
戻りloc_var1 in_flag他loc_var2の場合は
リターンinner_func
clo_func = outer_func(真)
印刷clo_func(偽)
エラーメッセージ:
トレースバック(最新の呼び出しの最後): ファイル" G:\プロジェクトファイル\ Pythonのテスト\ Main.py "、行260、で、<モジュール> 印刷clo_func(偽) ファイル" G:\プロジェクトファイル\ Pythonのテスト\ Main.py "、行256、中inner_func リターン loc_var1 場合 in_flag 他loc_var2 NameError:自由変数『loc_var2 』割り当ての前に参照して範囲を囲みます
三つの例上記の上記の例では影の中に見出すことができるビット人工的に見えるが、実際にはエラーコードに多少類似していてもよいです。ここでは、それ自体があまりにも多くの注目を行う必要はありません。たとえば、合理性のために、概念を説明するだけです。
2.エラーの原因
パイソン以来、変数、関数、またはクラスの概念を宣言されていません。習慣に応じてCまたはC ++、Pythonで書かれた、あるエラーの原因を発見することは困難です。
このようなエラーの公式な解釈ではまず見て:
名前が全く見つからない場合は、
NameError
例外が発生します。名前がバインドされていないローカル変数を参照する場合は、UnboundLocalError
例外が発生します。UnboundLocalError
のサブクラスですNameError
。
おそらくそれは意味します:
あなたは変数を参照するが、変数名が見つからない場合は、エラーの種類はNameErrorです。名前はまだローカル変数名がバインドされていない場合は、エラーのタイプはNameErrorですUnboundLocalError错误
。
次NameErrorこのタイプのエラーは、よりよいそれらのいくつかを理解することがあります。
1 my_functionの() 2 デフは、my_function(): 3つの パス
DEFはmy_functionには、my_functionに結合したときにPythonインタプリタは、()を実行しますが、今回も実行するためには、my_functionエントリメモリ機能を表している場合。したがって、my_functionのを使用する前に、NameErrorエラーする必要があります。
次に、変数の使用、上記の最初の例では、代入演算子(結合操作とみなすことができ、バック言う)に言及する場合、なぜそれが間違っているを持っていますか?可視性の決意も定義することができます
我々はそれを言うならば、割り当て操作が行われていないので、なぜローカル名前空間内の変数名が表示されていますか?(見えない、このエラーは次のようになります。NameError:グローバル名「XXX」が定義されていない、 に応じてUnboundLocalError
視認性の定義を決定することができます)
最終的には問題はどこですか?どのように正しくエラーの上記の3つの例を理解するには?
3.可視性とバインド
簡単にするために、これは名前空間の変数のルックアップ規則は、関連する概念をLGB説明していません。
CまたはC ++では、限り、変数または関数の宣言と定義として、そのまま使用することができます。しかし、Pythonで名前を引用するには、名前が見えると結合することでなければなりません。
いくつかの概念を初めて目:
- コードブロック:いくつかのPythonプログラムテキストは、単位(ユニット)として実行されます。例えばモジュール、他の身体機能およびクラスの定義。
- スコープ:コードブロックの名前で可視性を定義します。
- APOSブロック環境:コードブロックの場合、ブロックは、その範囲の可視名環境の全てのセットを構成します。
- バインド名前:以下の操作は結合操作と見なすことができます
- 形状関数のパラメータ
- 輸入申告
- のクラスとメソッドの定義
- 割り当て
- ループヘッダの
- 関連する変数の代入異常キャプチャ
- ローカル変数:名前がブロックにバインドされている場合、変数はブロックのローカル変数です。
- グローバル変数:名前はモジュールにバインドされている場合は、この変数はグローバル変数と呼ぶことにします。
- 自由変数:名前はブロックで参照が、コードブロック内で定義されていない場合、それは変数は自由変数であると呼ばれています。
無料変数はローカル変数で参照親関数クロージャにおける重要な概念は自由変数であり、かつ自由な変数は、セルオブジェクトに格納されます。クロージャは、関連記事で紹介されます。
スコープ機能で拡張性のある、しかし、クラス定義でスケーラブルなものではありません。
分析整頓:
私たちが知っている説明上記の概念のいくつかの後、限り、彼らのコードブロック内の変数は、バインド操作を持っているとして、スコープのコードブロックは、この変数に含まれます。
、(それが関数である場合、それはまた、スコープの定義を含む)実際の名前にも結合前の動作すなわち、結合操作の決定であり、そして結合した名前は、現在のスコープ内で可視です。
ここでは、名前バインディング操作の前に名前を参照する場合、ある問題があるでしょう、それは名前が表示されている場合でも、問題になります。
名前バインディングオペレーションは、コードブロック内のどこにでも発生した場合、ブロック内の名前のすべての使用は、現在のブロックへの参照として扱われます。これは、それがバインドされる前に名前がブロック内で使用されているエラーにつながることができます。このルールは微妙です。Pythonは宣言を欠いていると動作バインディング名は、コードブロック内のどこにでも発生することを可能にします。コードブロックのローカル変数は、名前バインディング操作のためのブロックのテキスト全体をスキャンすることによって決定することができます。
注上記の公式な説明と最後の文の最初の文という。
一般的にバインドされている名前バインディング動作中のすべては、ローカル変数とみなすことができ、コードブロックであり、結合操作が本当に実行された後に名前を参照することができるまでにはなかったです。
これらの概念では、3例以上の以下の分析で1つの一見ずつ。
4.解析エラー
ケースの4.1分析
割当は、このようloc_var視認性を有する、結合操作であり、特定の文字列オブジェクトにバインドされているためouter_func loc_varにおいて、我々は、変数を定義します。
しかし、スコープ内の関数を参照していませんでしたinner_funcに定義されている機能は、それの範囲内で定義されているすべてに拡張することができないのですか?
次の二つの段落では、内のビューのどのような公式のポイントを説明します。
名前は、コードブロックに使用されている場合には、最も内側のスコープを使用して解決されます。
この一節は、名前が参照されたとき、彼はスコープでの最近の名前で参照定義を見つけることを教えてくれる。明らかにloc_var + =この文「インナーFUNCでは、」最初の関数inner_func内部名loc_varのloc_varがあります。
声明は「内側FUNCに」loc_var = loc_var +に事実と同等であり、等号の右側にloc_var変数が最初に使用されますが、機能inner_funcの範囲であっloc_varので、ここでouter_func定義さloc_varを使用することはありません割り当ては、それほど可変inner_funcの範囲はinner_funcのローカル変数として表示されています。
しかし、声明の履行の完了を待つために、本当にloc_varをバインドすることができます。この文は、我々が以前inner_funcブロック内のローカル変数が束縛されて使用し、です。上記で定義されたエラーの種類、aはUnboundLocalError.
4.2ケースII分析
この場合、それは問題があるように見えますが、説明するのか分かりません。
リファレンスは、変数が正しく参照する必要がある、バインド操作の後に発生します。しかし、問題は、代入(結合操作)が実行されない場合があることです。あなたが結合しない操作を行いますので、確かに変数の参照がある場合は、これはすでに先に説明されています。
しかし、問題は、代入文が実行されていない場合は、現在のブロック内の変数はなぜ表示されている、ということもあるのでしょうか?
この問題では、実際には段落の説明を超えることがあります。コードブロックのローカル変数は名前バインド操作のためのブロックのテキスト全体をスキャンすることによって決定することができます。
限りバインディング動作(かかわらず、実際の実行されていない)として、次いで結合した名前は、ローカル変数として、現在のブロックが表示されています。コードが実行される前にスキャンテキストが発生します。
4.2ケースIII分析
この例では、自由変数の参照のクラスのための主要な問題を示しています。同時に、この例はまた、自由変数の使用を示しています。
閉鎖inner_funcを作成する場合、2つのローカル変数outer_func親とloc_var2としてloc_var1関数は、その内部inner_funcの範囲で表示されています。閉鎖では自由変数と呼ばouter_funcローカル変数の閉鎖後に返さ参照されます。
閉鎖中の自由変数は、彼らが特定のオブジェクトにバインドされていないかどうかに応じて参照することができます。
5.拡張ケース
次に、例を見て:
輸入SYS
デフadd_path(new_path):
path_listは=のsys.path
もしnew_pathないpath_listは内:
輸入SYS
sys.path.append(new_path)
add_path( './')
通常、不注意上記のこの間違いを犯すかもしれないが、これは典型的なUnboundLocalError
間違い。あなたは慎重に上記の分析を読み、理解していれば、私はそれがエラーの原因を理解することができるはずと信じています。それがクリアされない場合は、もう一度それを読んで:-)