How to map func_closure entries to variable names?

2024/10/5 5:22:14

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

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

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>/',{}]

That lambda function was created by this call:

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

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

Answer

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              421 LOAD_CONST               1 (<code object <lambda> at 0x10faec530, file "<stdin>", line 2>)24 MAKE_CLOSURE             027 CALL_FUNCTION            130 POP_TOP             31 LOAD_CONST               0 (None)34 RETURN_VALUE        

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

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)))
https://en.xdnf.cn/q/70526.html

Related Q&A

How to use the convertScaleAbs() function in OpenCV?

I am trying to convert an image back to grayscale after applying Sobel filtering on it. I have the following code: import numpy as np import matplotlib.pyplot as plt import cv2image = cv2.imread("…

Register a Hello World DBus service, object and method using Python

Im trying to export a DBus service named com.example.HelloWorld, with an object /com/example/HelloWorld, and method com.example.HelloWorld.SayHello that prints "hello, world" if the method i…

Python 3 Timedelta OverflowError

I have a large database that I am loading into an in-memory cache. I have a process that does this iterating through the data day by day. Recently this process has started throwing the following error:…

Constructing hierarchy from dictionary/JSON

Im looking for a way to create hierarchy in form of child parent relationship between two or more instances of same class.How would one go about creating such objects from nested dictionary like in exa…

PyPy file append mode

I have code like this:f1 = open(file1, a) f2 = open(file1, a)f1.write(Test line 1\n) f2.write(Test line 2\n) f1.write(Test line 3\n) f2.write(Test line 4\n)When this code is run with standard Python 2.…

Clean up ugly WYSIWYG HTML code? Python or *nix utility

Im finally upgrading (rewriting ;) ) my first Django app, but I am migrating all the content. I foolishly gave users a full WYSIWYG editor for certain tasks, the HTML code produced is of course terribl…

Using config files written in Python [closed]

Closed. This question is opinion-based. It is not currently accepting answers.Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.Clo…

Model not defined when using foreign key to second model

Im trying to create several relationships between some models such as User and Country. When I try to syncdb, my console outputs "Name Country is not defined". Here is the code: class User(mo…

Sending a POST request to my RESTful API(Python-Flask), but receiving a GET request

Im trying to send a trigger to a Zapier webhook in the form of a POST request containing JSON. It works fine if I just send the POST request through a local python script.What I want to do is create a …

django deploy to Heroku : Server Error(500)

I am trying to deploy my app to heroku. Deploy was done correctly but I got Server Error(500). When I turned DEBUG true, Sever Error doesnt occurred. So I think there is something wrong with loading st…