質問はすでに aaronasterling によって回答されています
ただし、誰かが内部で変数がどのように格納されるかに興味があるかもしれません。
スニペットに来る前に:
クロージャーは、囲んでいる環境から変数を継承する関数です。I / Oを実行する別の関数に引数として関数コールバックを渡すと、このコールバック関数は後で呼び出され、この関数は(ほとんど魔法のように)宣言されたコンテキストと使用可能なすべての変数を記憶しますその文脈で。
関数が自由変数を使用しない場合、クロージャーは形成されません。
自由変数を使用する別の内部レベルがある場合- 以前のすべてのレベルで字句環境が保存されます(例:最後)
python <3.Xまたはpython> 3.Xの関数属性func_closure
は、自由変数を保存します。__closure__
Pythonのすべての関数にはこのクロージャー属性がありますが、無料の変数がない場合はコンテンツを保存しません。
例:クロージャの属性ですが、内部にコンテンツはありません。
>>> def foo():
... def fii():
... pass
... return fii
...
>>> f = foo()
>>> f.func_closure
>>> 'func_closure' in dir(f)
True
>>>
注意:クロージャーを作成するには、無料変数が必要です。
上記と同じスニペットを使用して説明します。
>>> def make_printer(msg):
... def printer():
... print msg
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer() #Output: Foo!
そして、すべてのPython関数にはクロージャー属性があるので、クロージャー関数に関連付けられている囲んでいる変数を調べてみましょう。
これfunc_closure
は関数の属性ですprinter
>>> 'func_closure' in dir(printer)
True
>>> printer.func_closure
(<cell at 0x108154c90: str object at 0x108151de0>,)
>>>
このclosure
属性は、外側のスコープで定義された変数の詳細を含むセルオブジェクトのタプルを返します。
func_closureの最初の要素。Noneまたは関数の自由変数のバインディングを含むセルのタプルであり、読み取り専用です。
>>> dir(printer.func_closure[0])
['__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__',
'__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
>>>
ここでは、上記の出力で確認できますcell_contents
。何が格納されているかを見てみましょう。
>>> printer.func_closure[0].cell_contents
'Foo!'
>>> type(printer.func_closure[0].cell_contents)
<type 'str'>
>>>
そのため、関数を呼び出すと、printer()
内に保存されている値にアクセスしますcell_contents
。これは、「Foo!」という出力を取得する方法です。
ここでも、上記のスニペットといくつかの変更を使用して説明します。
>>> def make_printer(msg):
... def printer():
... pass
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer.func_closure
>>>
上のスニペットでは、printer関数内でmsgを印刷しないので、フリー変数は作成されません。自由変数がないため、クロージャー内にコンテンツはありません。これがまさに上記のとおりです。
今、私はすべてをクリアするために、別の異なるスニペットを説明しますFree Variable
とClosure
:
>>> def outer(x):
... def intermediate(y):
... free = 'free'
... def inner(z):
... return '%s %s %s %s' % (x, y, free, z)
... return inner
... return intermediate
...
>>> outer('I')('am')('variable')
'I am free variable'
>>>
>>> inter = outer('I')
>>> inter.func_closure
(<cell at 0x10c989130: str object at 0x10c831b98>,)
>>> inter.func_closure[0].cell_contents
'I'
>>> inn = inter('am')
したがって、func_closure
プロパティはクロージャーセルのタプルであることがわかり、それらとその内容を明示的に参照できます。セルにはプロパティ "cell_contents"があります。
>>> inn.func_closure
(<cell at 0x10c9807c0: str object at 0x10c9b0990>,
<cell at 0x10c980f68: str object at 0x10c9eaf30>,
<cell at 0x10c989130: str object at 0x10c831b98>)
>>> for i in inn.func_closure:
... print i.cell_contents
...
free
am
I
>>>
ここでを呼び出すとinn
、すべての保存自由変数が参照されるので、I am free variable
>>> inn('variable')
'I am free variable'
>>>