Python3の時間については、完全な回答がなかったので、こちらで回答しました。ここで説明する内容のほとんどは、Python 3 ドキュメントの4.2.2 名前の解決で詳しく説明されています。
他の回答で提供されているように、ローカル、エンクロージング、グローバル、ビルトインの 4 つの基本スコープ、LEGB があります。これらに加えて、クラス内で定義されたメソッドを囲むスコープを含まないクラス bodyという特別なスコープがあります。クラス本体内の割り当ては、そこからの変数をクラス本体にバインドします。
特に、and以外のブロック文は変数スコープを作成しません。Python 2 では、リスト内包表記は変数スコープを作成しませんが、Python 3 では、リスト内包表記内のループ変数が新しいスコープで作成されます。def
class
クラス本体の特性を示すため
x = 0
class X(object):
y = x
x = x + 1 # x is now a variable
z = x
def method(self):
print(self.x) # -> 1
print(x) # -> 0, the global x
print(y) # -> NameError: global name 'y' is not defined
inst = X()
print(inst.x, inst.y, inst.z, x) # -> (1, 0, 1, 0)
したがって、関数本体とは異なり、クラス本体で変数を同じ名前に再割り当てして、同じ名前のクラス変数を取得できます。この名前をさらに検索すると、代わりにクラス変数に解決されます。
Python を初めて使用する多くの人にとって大きな驚きの 1 つは、for
ループが変数のスコープを作成しないことです。Python 2 では、リスト内包表記もスコープを作成しません (ジェネレーターと辞書内包表記は作成します!) 代わりに、関数またはグローバル スコープで値をリークします。
>>> [ i for i in range(5) ]
>>> i
4
内包表記は、Python 2 のラムダ式内で変更可能な変数を作成するための狡猾な (場合によってはひどい) 方法として使用できます。ラムダ式はdef
ステートメントのように変数スコープを作成しますが、ラムダ内ではステートメントは許可されません。割り当てが Python のステートメントであることは、ラムダでの変数の割り当てが許可されていないことを意味しますが、リスト内包表記は式です...
この動作は Python 3 で修正されました。内包式やジェネレーターが変数をリークすることはありません。
グローバルは実際にはモジュール スコープを意味します。メインの python モジュールは__main__
; インポートされたすべてのモジュールは、sys.modules
変数を介してアクセスできます。アクセスするには、または;__main__
を使用できます。そこにアクセスして属性を割り当てることはまったく問題ありません。これらは、メイン モジュールのグローバル スコープ内の変数として表示されます。sys.modules['__main__']
import __main__
名前が現在のスコープ (クラス スコープを除く) に割り当てられている場合、その名前はそのスコープに属していると見なされます。まだ、またはまったくない)、または最後にグローバルスコープ。変数がローカルと見なされているが、まだ設定されていないか削除されている場合、変数値を読み取るUnboundLocalError
と、 のサブクラスである が生成されNameError
ます。
x = 5
def foobar():
print(x) # causes UnboundLocalError!
x += 1 # because assignment here makes x a local variable within the function
# call the function
foobar()
スコープは、global キーワードを使用して、グローバル (モジュール スコープ) 変数を明示的に変更することを宣言できます。
x = 5
def foobar():
global x
print(x)
x += 1
foobar() # -> 5
print(x) # -> 6
これは、スコープを囲んでいる場合でも可能です。
x = 5
y = 13
def make_closure():
x = 42
y = 911
def func():
global x # sees the global value
print(x, y)
x += 1
return func
func = make_closure()
func() # -> 5 911
print(x, y) # -> 6 13
Python 2 では、囲んでいるスコープの値を変更する簡単な方法はありません。通常、これは、長さが 1 のリストなど、変更可能な値を持つことによってシミュレートされます。
def make_closure():
value = [0]
def get_next_value():
value[0] += 1
return value[0]
return get_next_value
get_next = make_closure()
print(get_next()) # -> 1
print(get_next()) # -> 2
ただし、python 3では、nonlocal
が救助に来ます:
def make_closure():
value = 0
def get_next_value():
nonlocal value
value += 1
return value
return get_next_value
get_next = make_closure() # identical behavior to the previous example.
nonlocal
ドキュメントによると、
非ローカル ステートメントにリストされた名前は、グローバル ステートメントにリストされた名前とは異なり、囲んでいるスコープ内の既存のバインディングを参照する必要があります (新しいバインディングを作成するスコープを明確に決定することはできません)。
つまりnonlocal
、常に名前がバインドされている最も内側の外側の非グローバル スコープを参照します (つまり、割り当てられ、for
ターゲット変数として、with
句内で、または関数パラメーターとして使用されることを含みます)。
現在のスコープまたは外側のスコープに対してローカルであると見なされない変数は、グローバル変数です。グローバル名は、モジュールのグローバル ディクショナリで検索されます。見つからない場合、グローバルは builtins モジュールから検索されます。モジュールの名前が python 2 から python 3 に変更されました。Python 2 ではそうでしたが__builtin__
、Python 3 では と呼ばれるようになりましbuiltins
た。builtins モジュールの属性に割り当てると、そのモジュールが同じ名前の独自のグローバル変数でそれらをシャドウしない限り、読み取り可能なグローバル変数として、その後任意のモジュールに表示されます。
組み込みモジュールを読むことも役に立ちます。ファイルの一部で python 3 スタイルの print 関数が必要であるが、ファイルの他の部分ではまだprint
ステートメントを使用しているとします。print
Python 2.6-2.7 では、次の方法で Python 3関数を取得できます。
import __builtin__
print3 = __builtin__.__dict__['print']
は、from __future__ import print_function
実際には Python 2 のどこにも関数をインポートしません。代わりに、現在のモジュール内のステートメントprint
の解析規則を無効にし、他の変数識別子と同様に処理して、関数を組み込みで検索できるようにします。print
print
print