Where does Python store the name binding of function closure?

天涯浪子 提交于 2019-12-03 13:26:52
Bakuriu

This depends on the python implementation. I assume you mean CPython.

The __code__ (or func_code) has a co_freevars attribute that contains the name of all non-local variables (they are called "free vars" as if a python function was a logical formula where the arguments and local variables are quantified variables)

From these various attribute you can obtain a mapping from local and non-local names to cells.

In [35]: function.__code__.co_freevars
Out[35]: ('somevar',)

The co_varnames attribute lists all locally define names:

In [36]: function.__code__.co_varnames
Out[36]: ()
In [37]: def outer():
    ...:     somevar = ["stackoverflow"]
    ...:     def inner():
    ...:         x = 1
    ...:         somevar.append(5)
    ...:         return somevar
    ...:     return inner
    ...: 
    ...: function = outer()

In [38]: function.__code__.co_varnames
Out[38]: ('x',)

While co_cellvars says which local names are used by inner functions:

In [43]: outer.__code__.co_cellvars
Out[43]: ('somevar',)

All closure functions have __closure__ attribute. This attribute returns a tuple of cell objects. And The cell object has cell_contents attribute which stores the value of variable.

In [44]: function.__closure__
Out[44]: (<cell at 0x7f4e06b002b8: list object at 0x7f4e06b522c8>,)
In [45]: function.__closure__[0].cell_contents
Out[45]: ["stackoverflow"]

Luckily for us, functions in Python are first class objects. So we can gain a little more understanding of the closures by inspecting the function objects. And all Python functions have a closure attribute that lets us examine the enclosing variables associated with a closure function.

>>> def f():
...     pass
...
>>> repr(f); repr(f.__closure__)
'<function f at 0x0153A330>'
'None'
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!