Python 名前空間とスコープ
Python の名前空間とスコープ
このチュートリアルでは、名前空間、名前からオブジェクトへのマッピング、および変数のスコープについて学習します。
Python の名前とは?
「The Zen of Python」を読んだことがある場合 (type import this
Python インタプリタでは)、最後の行には、名前空間は素晴らしいアイデアの 1 つです。もっとやりましょう! では、これらの不思議な名前空間とは何ですか?最初に名前を見てみましょう。
名前 (識別子とも呼ばれます) は、単にオブジェクトに付けられた名前です。 Python ではすべてがオブジェクトです。名前は、基になるオブジェクトにアクセスする方法です。
たとえば、代入 a = 2
を行うとき 、 2
はメモリに格納されたオブジェクトで、a は、関連付ける名前です。組み込み関数 id()
を使用して、オブジェクトの (RAM 内の) アドレスを取得できます。 .使い方を見てみましょう。
# Note: You may get different values for the id
a = 2
print('id(2) =', id(2))
print('id(a) =', id(a))
出力
id(2) = 9302208 id(a) = 9302208
ここでは、両方とも同じオブジェクト 2
を参照しています。 、つまり、同じ id()
を持っています .物事をもう少し面白くしましょう。
# Note: You may get different values for the id
a = 2
print('id(a) =', id(a))
a = a+1
print('id(a) =', id(a))
print('id(3) =', id(3))
b = 2
print('id(b) =', id(b))
print('id(2) =', id(2))
出力
id(a) = 9302208 id(a) = 9302240 id(3) = 9302240 id(b) = 9302208 id(2) = 9302208
上記の一連の手順で何が起こっていますか?これを図で説明しましょう:
<図>
最初はオブジェクト 2
が作成され、名前 a a = a+1
を実行すると、それに関連付けられます 、新しいオブジェクト 3
が作成され、現在 a はこのオブジェクトに関連付けられています。
id(a)
に注意してください および id(3)
同じ値を持っています。
さらに b = 2
の場合 が実行され、新しい名前 b 前のオブジェクト 2
に関連付けられます .
Python は新しい複製オブジェクトを作成する必要がないため、これは効率的です。この名前バインディングの動的な性質により、Python は強力になります。名前はあらゆるタイプのオブジェクトを参照できます。
>>> a = 5
>>> a = 'Hello World!'
>>> a = [1,2,3]
これらはすべて有効で、a は、異なるインスタンスで 3 つの異なるタイプのオブジェクトを参照します。関数もオブジェクトなので、名前で参照することもできます。
def printHello():
print("Hello")
a = printHello
a()
出力
Hello
同じ名前 a 関数を参照でき、この名前を使用して関数を呼び出すことができます。
Python の名前空間とは?
名前が何であるかを理解したので、名前空間の概念に進むことができます。
簡単に言うと、名前空間は名前の集まりです。
Python では、名前空間を、定義したすべての名前を対応するオブジェクトにマッピングしたものと考えることができます。
異なる名前空間は同時に共存できますが、完全に分離されています。
すべての組み込み名を含む名前空間は、Python インタープリターを開始すると作成され、インタープリターが実行される限り存在します。
これが id()
のような組み込み関数が 、 print()
などは、プログラムのどの部分からでもいつでも利用できます。各モジュールは独自のグローバル名前空間を作成します。
これらの異なる名前空間は分離されています。したがって、異なるモジュールに存在する可能性のある同じ名前は衝突しません。
モジュールは、さまざまな機能とクラスを持つことができます。関数が呼び出されると、すべての名前が定義されたローカル名前空間が作成されます。クラスの場合も同様です。次の図は、この概念を明確にするのに役立ちます。
<図>Python 変数のスコープ
さまざまな一意の名前空間が定義されていますが、プログラムのすべての部分からすべてにアクセスできるとは限りません。スコープの概念が登場します。
スコープは、プレフィックスなしで名前空間に直接アクセスできるプログラムの部分です。
いつでも、少なくとも 3 つのネストされたスコープがあります。
<オール>関数内で参照が行われると、名前はローカル名前空間で検索され、次にグローバル名前空間で検索され、最後に組み込み名前空間で検索されます。
別の関数内に関数がある場合、新しいスコープはローカル スコープ内にネストされます。
Python でのスコープと名前空間の例
def outer_function():
b = 20
def inner_func():
c = 30
a = 10
ここで、変数 a はグローバル名前空間にあります。変数 b outer_function()
のローカル名前空間にあります と c inner_function()
のネストされたローカル名前空間にあります .
inner_function()
にいるとき , c b 私たちにとってローカルです 非ローカルで a グローバルです。 c に新しい値を代入するだけでなく、読み取ることもできます ただし、b しか読み取れません そしてa inner_function()
から .
b に値を代入しようとすると 、新しい変数 b 非ローカル b とは異なるローカル名前空間に作成されます . a に値を代入すると同じことが起こります .
ただし、 a を宣言すると グローバルとして、すべての参照と代入はグローバル a に移動します .同様に、変数 b を再バインドする場合 、非ローカルとして宣言する必要があります。次の例は、これをさらに明確にします。
def outer_function():
a = 20
def inner_function():
a = 30
print('a =', a)
inner_function()
print('a =', a)
a = 10
outer_function()
print('a =', a)
ご覧のとおり、このプログラムの出力は
a = 30 a = 20 a = 10
このプログラムでは、3 つの異なる変数 a 別々の名前空間で定義され、それに応じてアクセスされます。次のプログラムでは、
def outer_function():
global a
a = 20
def inner_function():
global a
a = 30
print('a =', a)
inner_function()
print('a =', a)
a = 10
outer_function()
print('a =', a)
プログラムの出力は次のとおりです。
a = 30 a = 30 a = 30
ここでは、すべての参照と代入はグローバル a に対するものです。 キーワード global
の使用による .
Python