Python 如何将func_闭包项映射到变量名?

Python 如何将func_闭包项映射到变量名?,python,python-2.x,cpython,Python,Python 2.x,Cpython,我有一个在这个函数中创建的lambda对象: def add_url_rule(self, rule, endpoint=None, view_func=None, **options): self.record(lambda s: s.add_url_rule(rule, endpoint, view_func, **options)) (<cell at 0x3eb89f0: str object at 0x2fb4378>, <cell at

我有一个在这个函数中创建的lambda对象:

def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
    self.record(lambda s:
        s.add_url_rule(rule, endpoint, view_func, **options))
(<cell at 0x3eb89f0: str object at 0x2fb4378>,
 <cell at 0x3eb8a28: function object at 0x3cb3a28>,
 <cell at 0x3eb8a60: str object at 0x3ebd090>,
 <cell at 0x3eb8b08: dict object at 0x3016ec0>)
使用lambda函数对象的
func_closure
,我可以访问lambda函数的闭包范围:

def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
    self.record(lambda s:
        s.add_url_rule(rule, endpoint, view_func, **options))
(<cell at 0x3eb89f0: str object at 0x2fb4378>,
 <cell at 0x3eb8a28: function object at 0x3cb3a28>,
 <cell at 0x3eb8a60: str object at 0x3ebd090>,
 <cell at 0x3eb8b08: dict object at 0x3016ec0>)
该lambda函数是通过此调用创建的:

add_url_rule('/<categId>/', 'categoryDisplay', rh_as_view(RHCategoryDisplay))
add_url_规则('/'、'categoryDisplay',rh_as_视图(RHCategoryDisplay))
如您所见,顺序与函数的参数顺序或lambda中使用参数的顺序不匹配。虽然我可以根据其类型/内容很容易地找出哪个元素是什么,但我想以更简洁的方式来做

所以我的问题是:我如何将它与它们的原始变量名(或者至少在函数参数的情况下是位置)关联起来?

多亏了Freenode上python中的YHG1,我找到了:
func\u code.co\u freevars
是一个元组,包含闭包中元素的变量名

>>> func.func_code.co_freevars
('endpoint', 'view_func', 'rule', 'options')
因此,创建将名称映射到闭包值的dict很容易:

>>> dict(zip(func.func_code.co_freevars,
             (c.cell_contents for c in func.func_closure)))
{'endpoint': 'categoryDisplay',
 'options': {},
 'rule': '/<categId>/',
 'view_func': <function indico.web.flask.util.RHCategoryDisplay>}
dict(zip)(func.func\u code.co\u freevars, (函数闭包中c的c.cell\u内容) {'endpoint':'categoryDisplay', “选项”:{}, “规则”:“/”, “查看函数”:
闭包由
加载闭包创建
字节码,顺序与字节码的顺序相同:

>>> dis.dis(add_url_rule)
  2           0 LOAD_FAST                0 (self)
              3 LOAD_ATTR                0 (record)
              6 LOAD_CLOSURE             0 (endpoint)
              9 LOAD_CLOSURE             1 (options)
             12 LOAD_CLOSURE             2 (rule)
             15 LOAD_CLOSURE             3 (view_func)
             18 BUILD_TUPLE              4
             21 LOAD_CONST               1 (<code object <lambda> at 0x10faec530, file "<stdin>", line 2>)
             24 MAKE_CLOSURE             0
             27 CALL_FUNCTION            1
             30 POP_TOP             
             31 LOAD_CONST               0 (None)
             34 RETURN_VALUE        

看起来先是关键字参数,然后是位置参数,然后是综合参数。这是用Python2还是用Python3测试的?我用的是Python2.7,但它需要支持2.6和2.7。我不认为这两个版本之间有任何相关的变化。使用2.7和你函数的简化版本,我得到了一个不同的顺序。很有意思。啊,我想在这里回答为什么它们是按顺序排列的。如果您能就这个答案(相关问题,python 3)提供任何见解,我将不胜感激。但我所能做的就是检查我在回答中使用的引用是否仍然适用于。然而,我并不期望它发生变化。@Arceld快速扫描我在回答中提到的
compile.c
中的相同函数,可以发现没有任何变化
co_freevars
以与闭包单元格相同的顺序列出名称。@Arceldon:此外,显式地依赖于此顺序。非常感谢,非常感谢您的帮助/澄清。