Python introspection: how to determine which fields are accessible from a method

I need to do black and dirty magic with Python.

Following my previous question on Lazy data-flow (table properties) with dependencies in Python, now I would like to populate a list of fields, the derived property depends on automatically, checking the calculation function.

I think I could use the func_code.co_names attribute, but I'm not very sure if there are any caveats there, and the documentation doesn’t help much.

Any ideas?

+4
source share
1 answer

Unfortunately, func_code.co_names unlikely to help many. This contains all the names that are available in the code segment, including global variables, in order of appearance.

 class Test(object): def calc_a(self): return self.b + self.c def calc_x(self): return self.ya + self.yb >>> Test.calc_a.func_code.co_names ('b', 'c') >>> Test.calc_x.func_code.co_names ('y', 'a', 'b') 

It is impossible to specify from this array if "a" and "b" are loaded from "self" or from "self.y". Typically, the only way to find out the access pattern for small code without executing it is to disassemble it.

 >>> import dis >>> dis.dis(Test.calc_x) 23 0 LOAD_FAST 0 (self) 3 LOAD_ATTR 0 (y) 6 LOAD_ATTR 1 (a) 9 LOAD_FAST 0 (self) 12 LOAD_ATTR 0 (y) 15 LOAD_ATTR 2 (b) 18 BINARY_ADD 19 RETURN_VALUE 

We see that the function loads the variable "self" (which is always co_varnames[0] for the associated function), then the attribute "y" ( co_names[0] ) is loaded from this object, and then the attribute 'a' ( co_names[1] loaded from this object co_names[1] ). The second stack object is popped from self.yb, then two are added.

Look at the source dis.py in the standard library to see how the Python C binary is disassembled. Loads of the 0th variable will be important for related functions. Another convenient point is that the arguments to the co_varnames[:co_argcount] function (the rest or varnames are locales), and co_freevars are variables from the closing non-global area.

+2
source

Source: https://habr.com/ru/post/1384302/


All Articles