List all the internal functions of a function?

In python, you can make fname.__code__.co_names to get a list of functions and global things that reference a function. If I do fname.__code__.co_varnames , this includes internal functions, I suppose.

Is there a way to essentially make inner.__code__.co_names ? starting with a line that looks like 'inner' , how co_varnames return?

+6
source share
2 answers

I do not think that you can check the code object, because the internal functions are lazy, and their code objects are created only in time. Instead, you most likely want to take a look at the ast module. Here is a quick example:

 import ast, inspect # this is the test scenario def function1(): f1_var1 = 42 def function2(): f2_var1 = 42 f2_var2 = 42 def function3(): f3_var1 = 42 # derive source code for top-level function src = inspect.getsource(function1) # derive abstract syntax tree rooted at top-level function node = ast.parse(src) # next, ast walk method takes all the difficulty out of tree-traversal for us for x in ast.walk(node): # functions have names whereas variables have ids, # nested-classes may all use different terminology # you'll have to look at the various node-types to # get this part exactly right name_or_id = getattr(x,'name', getattr(x,'id',None)) if name_or_id: print name_or_id 

Results: function1, function2, f1_var1, function3, f2_var1, f2_var2, f3_var1. Mandatory disclaimer: there is probably no good reason for this kind of thing .. but have fun :)

Oh, and if you only need internal function names?

 print dict([[x.name,x] for x in ast.walk(ast.parse(inspect.getsource(some_function))) if type(x).__name__=='FunctionDef']) 
+3
source

In Python 3.4+, you can get names using dis.get_instructions . To support nested functions, you also need to recursively iterate over each code object that you encounter:

 import dis import types def get_names(f): ins = dis.get_instructions(f) for x in ins: try: if x.opcode == 100 and '<locals>' in next(ins).argval\ and next(ins).opcode == 132: yield next(ins).argrepr yield from get_names(x.argval) except Exception: pass 

Demo:

 def func(): x = 1 y = 2 print ('foo') class A: def method(self): pass def f1(): z = 3 print ('bar') def f2(): a = 4 def f3(): b = [1, 2, 3] def f4(): pass print(list(get_names(func))) 

Outputs:

 ['f1', 'f2', 'f3', 'f4'] 
+3
source

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


All Articles