名前空間とスコープ
関数内で宣言された変数(local変数)、仮引数はその関数内でのみ有効です。
仮引数 a と b を合計する関数get_price()を定義します。
def get_price(a, b): return a + b print(get_price(300, 700))
結果は下記のようになります。
1000
ではその点を以下見ていきましょう。
global変数
animal というglobal変数を宣言して print してみます。
animal = 'cat' print(animal)
cat と表示されます。
cat
次に、関数 f() 内でglobal変数を 実行してみます。
animal = 'cat'
def f():
print(animal)
f()
同じように実行されます。
cat
ここでの変数 animal は 関数外で宣言されたという意味で、 global(グローバル)変数と呼ばれます。
local変数
では、関数 f() 内で、変数(ここでは同名のanimal)を宣言し実行してみます。
def f():
animal = 'dog'
print('local : ', animal)
f()
次のように出力されます。
local : dog
このように関数内で宣言された変数は、local(ローカル)変数と呼ばれます。
では、global変数と local変数を同時に使うとどうなるでしょう?
animal = 'cat' def f(): animal = 'dog' print('local : ', animal) f() print('global : ', animal)
global変数(cat), local変数(dog) 各々出力されます。
local : dog global : cat
最初に述べた重要ルールを思い起こしてください。:
関数 f() 内でlocal変数を宣言すると、変数の効果範囲スコープ(scope)は関数内に限られます。
そこで、次のようにprint (animal)を、変数宣言の前に記述するとどうなるでしょう?
animal = 'cat'
def f():
print(animal)
animal = 'dog'
print('local', animal)
f()
print('global :', animal)
エラーが帰ります。
Traceback (most recent call last):
File "/home/ec2-user/environment/Myapp.py", line 7, in <module>
f()
File "/home/ec2-user/environment/Myapp.py", line 3, in f
print(animal)
UnboundLocalError: local variable 'animal' referenced before assignment
local variable ‘animal’ referenced before assignment
*UnboundLocalError: ローカル変数 animal が割り当てられる前に、参照されるエラーです。
関数内でanimal(cat)を宣言すると、dogが有効になり、宣言の前にprintされるので、エラーが返りました。
では、関数内で global 変数を書き換えるにはどうしたらよいでしょうか?
関数内でglobal変数を宣言する。
関数内で global 変数を書き換える方法は、global を animal に加え、local変数をglobal変数に変更します。
animal = 'cat'
def f():
global animal
animal = 'dog'
print('local :' , animal)
f()
print('global :', animal)
local : dog global : dog
cat が dog に書き換わりました。
locals() と globals()
locals()
:関数内であるローカル領域の変数の値を全て辞書形式で返してくれます。
def f(): animal = 'dog' print('local', locals()) f()
関数 f() 内の全ての変数 animal を辞書形式で返してくれます。
local {'animal': 'dog'}
globals()
:グローバル領域の変数の値を全て辞書形式で返してくれます。
animal = 'cat' print('global :', globals())
global : {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f89ae584c10>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/home/ec2-user/environment/Myapp.py', '__cached__': None, 'animal': 'cat'}
animal : cat 以外にも python 自身が事前に宣言している全ての変数が返されています。
__doc__の場合
""" Test Test ############## """ animal = 'cat' print('global :', globals())
下記の様に返ります。
global : {'__name__': '__main__', '__doc__': '\nTest Test ##############\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f83658a0c10>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/home/ec2-user/environment/Myapp.py', '__cached__': None, 'animal': 'cat'}
__name__ の場合
'__name__': '__main__'
となっており、
名前空間は main となり、一番の関数ということです。他の読み込まれたモジュールの場合は main になりません。
名前空間
名前空間とは、変数や関数の名前が所属している場所のことです。
変数や関数が所属する場所、つまりモジュールやクラスが名前空間になります。
異なる名前空間にある同じ名前のオブジェクトには何の関係もありません。覚えておきましょう。
関数 f の name 属性と doc 属性、および global 領域の名前空間を表示してみます。
animal = 'cat' def f(): """Test func doc""" print(f.__name__) print(f.__doc__) f() print('global :', __name__)
f Test func doc global : __main__
コメント