13

If I have a script like this:

import sys

def square(x):
    return x*x

def cube(x):
    return x**3

How can I return a list of all the functions defined locally in the program ['square', 'cube'], and not the ones imported.

They are included when I try dir() but so are all the variables and other imported modules. I don't know what to put into dir to refer to the locally executing file.

1
  • try locals(), but I'm not sure how helpful that would be Commented Aug 26, 2013 at 19:26

4 Answers 4

19
l = []
for key, value in locals().items():
    if callable(value) and value.__module__ == __name__:
        l.append(key)
print l

So a file with the content:

from os.path import join

def square(x):
    return x*x

def cube(x):
    return x**3

l = []
for key, value in locals().items():
    if callable(value) and value.__module__ == __name__:
        l.append(key)
print l

Prints:

['square', 'cube']

Local scopes also work:

def square(x):
    return x*x

def encapsulated():
    from os.path import join

    def cube(x):
        return x**3

    l = []
    for key, value in locals().items():
        if callable(value) and value.__module__ == __name__:
            l.append(key)
    print l

encapsulated()

Prints out only:

['cube']
Sign up to request clarification or add additional context in comments.

6 Comments

Even as a one_liner: functions = [name for (name, thing) in locals().items() if callable(thing])
I like this solution because it doesn't rely on importing other modules, but when I try this in my actual script, it includes 'value' as an entry in l for some reason that I can't figure out... "Value" doesn't appear elsewhere in the script.
@beroe are you doing it twice maybe?
1. If I have the answer of alecxe in the program along with this one, and it prints "value" from his assignment, so I guess it is working but affected by other calls to inspect()? 2 The one-liner by @9000 shows my imported functions too, perhaps because it omits val.__module__ == __name__ (There is also a typo with your closing brackets). This works: functions = [name for (name, thing) in locals().items() if (callable(thing) and thing.__module__ == __name__)]
Oh... key and value are in locals, and value is assigned the values of all the other local variables in sequence. On Python 3, this modifies the global variable dict while iterating over it, producing undefined behavior. On Python 2, it might still produce really weird results. It's probably best to encapsulate this in a function and use globals.
|
9

Use inspect module:

def is_function_local(object):
    return isinstance(object, types.FunctionType) and object.__module__ == __name__

import sys
print inspect.getmembers(sys.modules[__name__], predicate=is_function_local)

Example:

import inspect
import types
from os.path import join

def square(x):
    return x*x

def cube(x):
    return x**3

def is_local(object):
    return isinstance(object, types.FunctionType) and object.__module__ == __name__

import sys
print [name for name, value in inspect.getmembers(sys.modules[__name__], predicate=is_local)]

prints:

['cube', 'is_local', 'square']

See: no join function imported from os.path.

is_local is here, since it's a function is the current module. You can move it to another module or exclude it manually, or define a lambda instead (as @BartoszKP suggested).

3 Comments

Gives [('cube', <function cube at 0x0294AC70>), ('join', <function join at 0x025A58B0>), ('square', <function square at 0x028BBAB0>)] when from os.path import join added
@Marcin: That example only appears to exclude imported functions because built-in functions don't count for inspect.isfunction. The new version works, though.
I modified is_local to exclude itself, and this works. Thanks. return isinstance(object, types.FunctionType) and object.__module__ == __name__ and object.__name__ !='is_local'
6

Using Python 3.9.7, When trying the most upvoted answer:

l = []
for key, value in locals().items():
    if callable(value) and value.__module__ == __name__:
        l.append(key)
print(l)

I got the following error: Traceback (most recent call last): File "C:\Users\Name\Path\filename.py", line X, in for key, value in locals().items(): RuntimeError: dictionary changed size during iteration

Because the answer: locals() prints this:

'test_01': <function test_01 at 0x00000285B0F2F5E0>
'test_02': <function test_02 at 0x00000285B0F2FA60>

I just check if we get the string: "function" in the dictionary.

I used the following code to achieve my needs. Hope maybe this can help.

l = []
copy_dict = dict(locals())
for key, value in copy_dict.items():
    if "function" in str(value):
        l.append(key)
print(l)

Comments

3
import sys
import inspect
from os.path import join

def square(x):
    return x*x

def cube(x):
    return x**3

print inspect.getmembers(sys.modules[__name__], \
      predicate = lambda f: inspect.isfunction(f) and f.__module__ == __name__)

Prints:

[('cube', <function cube at 0x027BAC70>), ('square', <function square at 0x0272BAB0>)]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.