Reputation: 7728
The globals
function returns a dictionary that contains the functions in a module, and the dir
function returns a list that contains the names of the functions in a module, but they are in alphabetical order or are in a dictionary.
Is there a way to get the names of all the functions in a module in the order they appear in a file?
Upvotes: 3
Views: 493
Reputation: 23
My solution was to parse the ast. As it turns out elements in the ast tree are in the order they are parsed. Hence functions are in the order they appear in the file.
import inspect
import ast
def get_function_names_in_order_of_appearence(module_name):
this_source = inspect.getsource(module_name)
tree = ast.parse(this_source)
functions = []
for elem in tree.body:
if type(elem) is ast.FunctionDef:
this_func_name = elem.name
functions.append(this_func_name)
return functions
Assuming the module that is to be analyzed is:
# fancy_module
def z_func(x):
return x+1
def a_func(a, b):
pass
def b_func(mystr, **kw):
pass
Will give:
func_list = get_function_names_in_order_of_appearence(fancy_module)
for func in func_list:
print(func)
# -------
# output:
z_func
a_func
b_func
The advantage is you can add other stuff from the ast tree, like the signatures of the functions.
Upvotes: 0
Reputation: 184345
When I had a need like this, I used a decorator.
def remember_order(func, counter=[0]):
func._order = counter[0]
counter[0] += 1
return func
@remember_order
def foo():
print "foo"
@remember_order
def bar():
print "bar"
@remember_order
def baz():
print "baz"
Yes, you have to decorate each function individually. Explicit is better than implicit, as they say, and because you are doing something unnatural it's good to call it out as plainly as possible.
Now you want to get all the decorated functions in the order they were defined?
import sys
module = sys.modules[__name__] # get reference to current module
# you could also use a reference to some other module where the functions are
# get the functions in the order defined
funcs = sorted((func for func in
(getattr(module, name) for name in dir(module))
if callable(func) and hasattr(func, "_order")),
key = lambda func: func._order)
# call them in that order
for func in funcs:
func()
But it'd be easier to just give them names in alphabetical order...
Upvotes: 3
Reputation: 7728
Here is my solution. Read in the source file as a string, filter out lines that begin with def, strip leading whitespace and extract the substring between the first space and first left paren.
def extract_fns(filename):
with open(filename) as f:
lines = f.readlines()
return [line.split(' ', 1)[1].split('(')[0] for line in lines
if line.strip().startswith('def')]
Upvotes: 3