特徴
pythonのスコープは静的であり、ソースコードで変数名が割り当てられている位置によって、アクセスできる変数のスコープが決まります。つまり、Python変数のスコープは、ソースコード内の変数の場所によって決定されます。 Pythonのすべてのステートメントブロックにスコープがあるわけではありません。変数がモジュール(モジュール)、クラス(クラス)、定義(関数)で定義されている場合にのみ、スコープの概念があります。
1. 関数内の変数は関数外からアクセスできません
def func():
variable =100print(variable)print(variable) # name 'variable' is not defined
**2. 関数の上位層にある変数(スカラー)は、読み取りのみ、再定義、初期化はできません。
def counter1():
n =0
def compute():
n = n +1 #nはスカラー(数値、文字列、浮動小数点数)であるため、Pythonプログラムは、「内部関数に同じ名前の変数または外部関数を参照するグローバル変数がある場合、,そして、この変数を変更します.次に、pythonはそれがローカル変数であると見なします,また、関数にはnの定義と割り当てがないため、エラーが報告されます
# y = n +1 #yに変更して大丈夫です
# return y
return n
return compute
variable =300
def test_scopt():print(variable) #このとき、ローカル変数変数が呼び出され、メモリオブジェクトにバインドされません。(定義と初期化なし、つまり割り当てなし)。基本的にLEGBルール
variable =200 #このため、以前に一度呼び出されたため、変数はローカル変数になります
# print(variable) #変数は新しいローカル変数であり、再定義されていませんが、バインドされていないため、以下に記述してもかまいません。
test_scopt()
Pythonのモジュールコードは実行前にプリコンパイルされませんが、モジュールの関数本体コードは実行前にプリコンパイルされるため、スコープ内のどこで変数名のバインドが発生しても、コンパイルできます。デバイスは認識しています。 Pythonは静的にスコープされた言語ですが、変数名のルックアップは動的に行われ、スコープの問題はプログラムが実行されるまで発見されません。
3. listやdictなどの複合変数の値は参照によって変更できます
def counter():
n =[0]
def compute():
n[0]+=1 #nではなくnの最初の値が変更されます
return n[0]return compute
func =counter()func() # 1func() # 2func() # 3
4. グローバルはグローバル変数を宣言します。グローバル変数をローカルで変更する場合は、グローバル変数をローカルで宣言する必要があります
def counter1():
n =0
def compute():
global n #グローバル変数をローカルで変更する場合は、グローバル変数をローカルで宣言する必要があります,ただし、グローバル変数nがないため、ここでエラーが発生します。
n +=1return n
return compute
# right
def counter1():
global n
n =0
def compute():
global n
n +=1return n
return compute
5. nonlocalキーワードは、関数または他のスコープで外部(非グローバル)変数を使用するために使用されます
def make_counter():
count =0
def counter():
nonlocal count #外部の非グローバル変数を使用する
count +=1return count
return counter
スコープの種類
Pythonでは、変数を使用する場合、事前に宣言する必要はありませんが、実際に使用する前に、メモリオブジェクト(定義、割り当て)にバインドする必要があります。この変数名のバインドは次のようになります。外側のスコープで同じ名前の変数をシールドしながら、現在のスコープに新しい変数を導入します。
L(ローカル)ローカルスコープ
ローカル変数:defキーワードで定義されたステートメントブロック、つまり関数で定義された変数に含まれます。関数が呼び出されるたびに、新しいローカルスコープが作成されます。 Pythonには再帰もあります。つまり、自分自身を呼び出すと、呼び出すたびに新しいローカル名前が作成されます。関数内の変数宣言は、グローバル変数として特に宣言されていない限り、デフォルトでローカル変数になります。場合によっては、グローバル変数を関数内で定義する必要があります。このとき、globalキーワードを使用して、変数のスコープをグローバルとして宣言できます。ローカル変数スコープはスタックのようなもので、ローカルスコープを作成した関数がアクティブかどうかに応じて一時的にのみ存在します。したがって、グローバル変数はモジュールファイルの実行中に常に存在し、メモリスペースを占有するため、一般に、グローバル変数をできるだけ少なく定義することをお勧めします。
注:関数内のグローバル変数に値を割り当てる必要がある場合は、関数内のグローバルステートメントを使用して変数をグローバル変数として宣言する必要があります。
E(囲んでいる)ネストされたスコープ
Eもdefキーワードに含まれ、EとLは相対的であり、Eも高レベル関数に関連するLです。 Lとの違いは、関数の場合、Lは関数で定義されたローカルスコープであり、Eは関数の親関数で定義されたローカルスコープであるということです。主にPythonクロージャを実現し、実装を増やします。
G(グローバル)グローバルスコープ
つまり、モジュール階層で定義された変数の場合、各モジュールはグローバルスコープです。つまり、モジュールファイルの最上位で宣言された変数はグローバルスコープを持ち、外部から見ると、モジュールのグローバル変数はモジュールオブジェクトの属性です。
注:グローバルスコープのスコープは、単一のモジュールファイルに制限されています
B(ビルトイン)ビルトインスコープ
組み込みモジュールで事前定義された変数など、システムの固定モジュールで定義された変数。
スコープチェーン:変数名解決のLEGBルール
変数名の検索優先度:ローカルスコープ、ネストされたスコープ、グローバルスコープ、組み込みスコープ
LEGBルール:関数で未決定の変数名が使用されている場合、Pythonは優先度に従って4つのスコープを順番に検索して、変数名の意味を決定します。最初にローカルスコープ(L)が検索され、次に上部のネストされた構造のdefまたはlambda関数のネストされたスコープ(E)、次にグローバルスコープ(G)、最後に組み込みスコープ(B)が検索されます。この検索原理に従って、最初に見つかった場所で停止します。見つからない場合は、NameErrorが発生します。
example 1
name ="lzl"
def f1():print(name)
def f2():
name ="eric"f1()f2() #関数が実行される前に、スコープチェーンが形成されています。この時点でf1()上位レベルは名前である必要があります='lzl'
example 2
def scope_test():
def do_local():
spam ="local spam" #この関数は別のスパム文字列変数を定義し、ライフサイクルはこの関数にのみあります。ここで、スパムを作成する場合、スパムと外部スパムは2つの変数です。= spam +「ローカルスパム」はエラーを報告します
def do_nonlocal():
nonlocal spam #外側のスパム変数testspamを使用する
spam ="nonlocal spam"
def do_global():
global spam
spam ="global spam"
spam ="test spam"do_local()print("After local assignmanent:", spam) # test spam
do_nonlocal()print("After nonlocal assignment:",spam) # nonlocal spam
do_global()print("After global assignment:",spam) # nonlocal spam ????最初にローカル変数を探します。見つかったローカル変数はすでに実行されています。_nonlocal()内部が変更されたため、出力は非ローカルスパムになります
scope_test()print("In global scope:",spam) # global spam
Recommended Posts