プログラミング言語の基本要素のひとつに変数がある。簡単に言えば、変数は実際の値を格納するメモリセルの抽象化レイヤーです。私たち開発者にとっては、物理的なメモリアドレスを覚えるよりも、メモリセルの名前を覚える方が簡単です。有効な名前は、数字だけでなく、「a」から「z」までの文字(小文字と大文字の両方)で構成することができます。名前には、スペースや、ウムラウトやハイフンなどの特殊文字は使えません。
さらに、変数は文字列(文字)、数字、リスト、他の変数への参照など、特定のデータ型を持っています。Pythonでは、同じ変数を再利用して、任意の型の値を格納することができます。型は、名前に割り当てられた値によって自動的に決定されます。特定の値を持つ変数を定義するには、次のように名前にその値を代入するだけです。
age = 42
name = "Dominic"
places = ["Berlin", "Cape Town", "New York"]
Python インタープリタは age
, name
, places
という3つの変数を作成し、最初の変数に 42 という値を、2番目の変数に “Dominic” という値を代入し、 places
は “Berlin”, “Cape Town”, “New York” という文字列を含む3要素のリストになっています。
名前空間
上記の変数はすべて同じ名前空間に属しており、したがって同じスコープを持っています。後でローカル変数として再定義されない限り、メインプログラムで定義された変数はグローバル名前空間に属し、Pythonプログラムのどの関数からもアクセスできます。次のコード例では、関数 info()
の中で name
と age
という2つの変数を使用して、このことを実証しています。
age = 42
name = "Dominic"
places = ["Berlin", "Cape Town", "New York"]
def info():
print("%s is %i years old." % (name, age))
return
info()
出力は、関数 info()
の print
ステートメントから得られる一行からなります。
$ python3 global.py
Dominic is 42 years old.
より正確には、すべてのモジュール、クラス、関数はそれ自身の名前空間を持ち、変数はそれにローカルに束縛されます。次の例では、2つの名前空間を利用しています。メインプログラムの外側のグローバルな名前空間と、単に output()
という名前の関数の内側のローカルな名前空間です。変数 place
はメインプログラム (6行目) に存在し、関数 output()
の2行目で新しい値を持つローカル変数として再定義されます。
def output():
place = "Cape Town"
print("%s lives in %s." % (name, place))
return
place = "Berlin"
name = "Dominic"
print("%s lives in %s." % (name, place))
output()
出力はこの2行からなり、1行目はメインプログラム(8行目)から、2行目は関数 output()
の3行目の print
ステートメントから出力されています。まず、メインプログラムの中で name
と place
という 2 つの変数が定義され (6行目と7行目)、標準出力に出力されます。関数 output()
を呼び出すと、2 行目で変数 place
がローカルに再定義され、代わりに name
がグローバルな名前空間から取得されます。この結果、以下のような出力が得られます。
$ python3 localscope.py
Dominic lives in Berlin.
Dominic lives in Cape Town.
異なるネームスペースのグローバル変数の変更
グローバル変数の値は、プログラム全体を通してアクセスすることができます。これを実現するために、Python では global
というキーワードを使用します。以下の関数はその使い方を示しており、変数 name
を関数の名前空間にインポートしています。
def location():
global place
place = "Cape Town"
return
place = "Berlin"
print(place)
location()
print(place)
変数 place
はメインプログラムの中ですでに定義されています (6行目)。2 行目でキーワード global
を使用すると、この変数は関数 location()
の中で使用できるようになり、すぐに別の値を設定することができます (3 行目)。このコードの出力は次のとおりです。
$ python3 globalscope.py
Berlin
Cape Town
2行目のようにキーワード global
を使用しない場合、変数 place
は関数 location()
の中でローカル変数として扱われ、メインプログラムの変数 place
は変更されません。
変数のスコープを検出する
Python には globals()
と locals()
という名前の 2 つの組み込みメソッドがあります。これらのメソッドにより、ある変数がグローバルネームスペースとローカルネームスペースのどちらに属しているかを判断することができます。以下の例では、これらのメソッドをどのように使用するかを示しています。
def calculation():
"do a complex calculation"
global place
place = "Cape Town"
name = "John"
print("place in global:", 'place' in globals())
print("place in local :", 'place' in locals())
print("name in global :", 'name' in globals())
print("name in local :", 'name' in locals())
return
place = "Berlin"
print(place)
calculation()
出力は以下のようになり、関数 calculation()
内の 2 つの変数 place
と name
のスコープが表示されます。
$ python3 variablelist.py
Berlin
place in global: True
place in local : False
name in global : False
name in local : True
グローバル変数の実践的な使用
関数内部でグローバル変数を使用したり変更したりすることは、非常に悪いプログラミングスタイルと見なされており、検出が困難な副作用を引き起こすからです。関数のパラメータを適切に使用することを強くお勧めします。
謝辞
本論文の作成にあたり、Mandy Neumeyerのサポートに感謝したい。
リンクと参考文献
- Bernd Klein: Global, Local and nonlocal Variables, https://www.python-course.eu/python3_global_vs_local_variables.php
- Variable scope and lifetime, University of Cape Town, http://python-textbok.readthedocs.io/en/1.0/Variables_and_Scope.html
- Python 3: globals(), https://docs.python.org/3/library/functions.html#globals
- Python 3: locals(), https://docs.python.org/3/library/functions.html#locals