如何将func_closure条目映射到变量名? [英] How to map func_closure entries to variable names?

查看:98
本文介绍了如何将func_closure条目映射到变量名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在此函数中创建了一个lambda对象:

I have a lambda object that is created in this function:

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))

使用lambda函数对象的 func_closure 我可以访问lambda函数的闭包范围:

Using func_closure of the lambda function object I can access the closure scope of the lambda function:

(<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>)

仔细研究一下(在每个 cell cell_contents 属性中对象)显示以下内容:

A closer look (at the cell_contents attribute of each cell object) shows me this:

>>> [c.cell_contents for c in func.func_closure]
['categoryDisplay',
 <function indico.web.flask.util.RHCategoryDisplay>,
 '/<categId>/',
 {}]

该lambda函数是通过以下调用创建的:

That lambda function was created by this call:

add_url_rule('/<categId>/', 'categoryDisplay', rh_as_view(RHCategoryDisplay))

如您所见,该顺序与函数的参数顺序或在lambda中使用参数的顺序不匹配。虽然我可以根据其类型/内容轻松地确定哪个元素是什么,但我想以一种更简洁的方式进行操作。

As you can see, the order does not match the argument order of the function or the order in which the arguments are used inside the lambda. While I could easily find out which element is what based on its type/content, I'd like to do it in a cleaner way.

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

So my question is: How can I associate it with their original variable names (or at least positions in case of function arguments)?

推荐答案

已创建闭包通过 LOAD_CLOSURE 字节码,按其字节码的排序顺序:

The closures are created by the LOAD_CLOSURE bytecode, in the same order as their bytecodes are ordered:

>>> 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        

因此顺序是在编译时由 compiler_make_closure() ;此函数使用 func.func_code.co_freevars 元组作为指南,该列以相同顺序列出了闭包。

so the order is determined at compile time, by compiler_make_closure(); this function uses the func.func_code.co_freevars tuple as a guide, which lists the closures in the same order.

func.func_code.co_freevars makecode ,并且元组是从python字典的键生成的,因此顺序是相反的任意的,与词典一样。如果您好奇,可以在 compiler_enter_scope() ,使用 dictbytype()实用程序功能来自编译器符号表中命名的所有自由变量,本身就是python字典。

func.func_code.co_freevars is set when creating a code object in makecode, and the tuple is generated from the keys of a python dictionary, so the order is otherwise arbitrary, as common for dictionaries. If you are curious, the dict is built in compiler_enter_scope(), using the dictbytype() utility function from all the free variables named in the compiler symbol table, itself a python dictionary.

因此,关闭的顺序确实是任意的(哈希表已排序),并且您将使用 func.func_code.co_freevars 元组(可以看作是编译器处理字典键的顺序的记录)以将名称附加到闭包上:

So, the order of the closures is indeed arbitrary (hash table ordered), and you'd use the func.func_code.co_freevars tuple (which can be seen as a record of the order the compiler processed the dictionary keys) to attach names to the closures:

dict(zip(func.func_code.co_freevars, (c.cell_contents for c in func.func_closure)))

这篇关于如何将func_closure条目映射到变量名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆