Where does Python store the name binding of function closure?

前端 未结 2 970
长发绾君心
长发绾君心 2020-12-16 04:35

So recently I understand the concept of function closure.

def outer():
    somevar = []
    assert \"somevar\" in locals() and not \"somevar\" in globals()
          


        
相关标签:
2条回答
  • 2020-12-16 04:53

    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"]
    
    0 讨论(0)
  • 2020-12-16 05:15

    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'
    
    0 讨论(0)
提交回复
热议问题