【问题标题】:Reflect / Inspect closed-over variables in Python在 Python 中反映/检查封闭变量
【发布时间】:2013-10-17 01:40:23
【问题描述】:

如果我有:

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

f2 = f(2)

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

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

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

【问题讨论】:

    标签: python closures


    【解决方案1】:

    您不必在此处使用inspect 模块。

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

    适用于 Python 2.7

    【讨论】:

    • 在 Python 3 中,使用 __code__.co_freevars__closure__cell_contents
    • @Leonardo.Z - 请查看我的回答并确认我问的问题,如果您在这里知识渊博。 OP (Des) 也是。
    【解决方案2】:

    您可以通过查看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 之前获得封闭变量名称。

    【讨论】:

      【解决方案3】:

      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,因此以上对于该特定情况就足够了。

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

      【讨论】:

      猜你喜欢
      • 2011-10-13
      • 1970-01-01
      • 2012-08-18
      • 2014-12-04
      • 2017-04-21
      • 2014-04-19
      • 2014-12-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多