11

如果我有:

def f(x):
  def g(y):
    return x + y
  return g

f2 = f(2)

有没有办法找到将使用的x绑定f2?我看了看,inspect但不知道有些frame东西是否适用。换句话说,我可以在closed_vars()下面定义一个:

def closed_vars(anF):
    ... return ...

assert closedVars(f2) == {'x': 2}
4

3 回答 3

7

您不必在inspect这里使用该模块。

>>> dict(zip(f2.func_code.co_freevars, (c.cell_contents for c in f2.func_closure)))
{'x': 2}

适用于 Python 2.7

于 2013-10-17T01:50:08.473 回答
5

您可以通过签出获取单元格内容f.func_closure(适用于 Python 2.7.5):

>>> def f(x):
...   def g(y):
...     return x + y
...   return g
... 
>>> f2 = f(2)
>>> [cell.cell_contents for cell in f2.func_closure]
[2]

Python 3.3 有一个inspect.getclosurevars功能:

获取 Python 函数或方法 func 中外部名称引用与其当前值的映射。返回一个命名元组ClosureVars(nonlocals, globals, builtins, unbound)。nonlocals 将引用的名称映射到词法闭包变量,将全局变量映射到函数的模块全局变量,将内置函数映射到函数体可见的内置函数。unbound 是函数中引用的一组名称,在给定当前模块全局变量和内置函数的情况下根本无法解析。

我还不确定您是否可以获得 Python 3.3 之前的封闭变量名称。

于 2013-10-17T01:44:01.177 回答
0

Python 3 更新 - 2019 年 2 月

特意把这个写出来:

def f(x):
    def g(y):
        return x + y
    return g

f2 = f(2)

def closedVars(anF):
    keys = f2.__code__.co_freevars
    values = [cell.cell_contents for cell in f2.__closure__]
    # keys and values definitely match in correct order in general case?
    return dict(zip(keys, values))

assert closedVars(f2) == {'x': 2}

我不太清楚,这也适用于上面标记为正确的答案,是(非局部闭包)变量名(__code__.co_freevars)的元组之间的顺序和变量值(f2.__closure__)的顺序是否保证匹配(操作所zip依赖的)。在用于提出问题的简单示例中,我们只处理一个变量x,因此上述内容足以满足该特定情况。

如果有人可以确认一般情况而不是仅仅假设它是这样的,那会很好吗?

于 2019-02-23T12:01:19.040 回答