内部関数(inner function)の使い方
pythonでは、関数の内部に関数を書くことができる。これを内部関数と言います。また、ノンローカル変数(nonlocal)として宣言すると内側の関数から外側の関数で宣言された変数を書き換えられるようになる。
- inner関数の書き方
def innner():
# inner関数の処理
# inner関数を呼び出す等outer関数で行う
内部関数でのnonlocalの使い方
pythonではノンローカル変数という変数があり、内部関数の名前空間から外部関数の名前空間にある変数にアクセスすることができる。
(ノンローカル変数についてはこちらでも記述してある)
- nonlocalを使わない場合(外部の関数の値は変更されない)
def inner():
outer_value = '内側で変更'
outer_value = '外'
inner() # inner関数を呼び出す
print(outer_value) # 「外」と表示
return outer_value
value = outer()
print(value) # '外'と表示(外部の関数の値は変更される)
- nonlocalを使う場合
def inner():
nonlocal outer_value # nonlocalを宣言
outer_value = '内側で変更' # 外側の関数の名前空間のouter_valueに'内側で変更'が代入される
outer_value = '外'
inner() # inner関数を呼び出す
print(outer_value) # 「内側で変更」と表示
return outer_value
value = outer()
print(value)
内部関数を用いたクロージャの定義
前述の通り、内部関数からは外部の関数の変数にアクセスして値を変更することはできないが、参照することはできる。
以下のように利用する。
- 内部関数から外部の変数へのアクセス
outer_value = '外'
def inner():
print(outer_value) # 外と表示
inner()
return outer_value
value = outer()
内部関数のこの性質を用いて、クロージャを作成する。
クロージャとは、
- 関数とその周囲の環境への参照の組み合わせ
のことを言う。
以下のようにすると、関数(inner)と周囲の環境(name)の組み合わせを返すことができる
- クロージャの定義
name = 'Taro'
def inner():
print(name) # nameを参照
return inner # 内部関数を返す
function = outer() # クロージャを変数functionに代入
function() # functionを実行
呼び出す際に、外部の変数に値を代入することができる。
- 外部の変数に値を代入
name = name
def inner():
print(name) # nameを参照
return inner # 内部関数を返す
function = outer('Jiro') # outerを引数Jiroにして呼び出し、クロージャを変数functionに代入
function() # functionを実行
関数を渡して、内部関数内で実行することもできる。
以下のように記述する。
- 内部関数に関数を渡す
def inner(*args):
print(func(*args)) # funcを用いて引数*argで実行する
return inner
def add(x, y):
return x + y
def sub(x, y):
return x-y
add_func = outer(add) # funcに関数addを入れてクロージャを返す
sub_func = outer(sub) # funcに関数subを入れてクロージャを返す
add_func(3, 3) # args=(3,3)でprint(add(*args))が実行され、6と表示
add_func(4, 5) # args=(4,5)でprint(add(*args))が実行され、9と表示
sub_func(10, 5) # args=(10,5)でprint(sub(*args))が実行され、5と表示
sub_func(20, 10) # args=(20,10)でprint(sub(*args))が実行され、10と表示