クロージャ

Python関数の書き方

Shayne Miel

Software Architect @ Duo Security

入れ子関数へ非ローカル変数を結び付ける

def foo():
  a = 5
  def bar():
    print(a)
  return bar

func = foo()

func()
5

クロージャ!

type(func.__closure__)
<class 'tuple'>
len(func.__closure__)
1
func.__closure__[0].cell_contents
5
Python関数の書き方

クロージャと削除

x = 25

def foo(value):
  def bar():
    print(value)
  return bar

my_func = foo(x)
my_func()
25
del(x)
my_func()
25
len(my_func.__closure__)
1
my_func.__closure__[0].cell_contents
25
Python関数の書き方

クロージャと上書き

x = 25

def foo(value):
  def bar():
    print(value)
  return bar

x = foo(x)
x()
25
len(x.__closure__)
1
x.__closure__[0].cell_contents
25
Python関数の書き方

定義 - 入れ子関数

入れ子関数: 別の関数内で定義された関数。

# outer function
def parent():
  # nested function
  def child():
    pass
  return child
Python関数の書き方

定義 - 非ローカル変数

非ローカル変数: 親関数で定義され、子関数で使用される変数。

def parent(arg_1, arg_2):
  # child() から見ると、
  # `value` と `my_dict`、そして `arg_1` と `arg_2` は
  # 非ローカル変数です。
  value = 22
  my_dict = {'chocolate': 'yummy'}

  def child():
    print(2 * value)
    print(my_dict['chocolate'])
    print(arg_1 + arg_2)

  return child
Python関数の書き方

クロージャ: 返された関数に結び付く非ローカル変数。

def parent(arg_1, arg_2):
  value = 22
  my_dict = {'chocolate': 'yummy'}

  def child():
    print(2 * value)
    print(my_dict['chocolate'])
    print(arg_1 + arg_2)

  return child

new_function = parent(3, 4)

print([cell.cell_contents for cell in new_function.__closure__])
[3, 4, 22, {'chocolate': 'yummy'}]
Python関数の書き方

なぜ重要か

デコレータで使う要素:

  • 関数はオブジェクト
  • 入れ子関数
  • 非ローカルスコープ
  • クロージャ
Python関数の書き方

Let's practice!

Python関数の書き方

Preparing Video For Download...