0

I have scraped some strings from emails into a list. The strings correspond to the names of functions which I want to be able to call later. I cannot call them in their current form so is there a way of converting the list of strings into a list of functions that I can call?

For example:

a = ['SU', 'BT', 'PL']
str = 'sdf sghf sdfgdf SU agffg BL asu'
matches = [x for x in a if x in str]
print(matches)

returns:

 ['SU', 'BL']

But I cannot call functions SU and BL from this list given the format.

5
  • You could make a dictionary of functions, where the string is a key, and the function is the value. Then run your_dict[key](). Did you try that? Commented Oct 13, 2021 at 10:05
  • The function name in Python serves as a variable itself. So what you actually want to do is retrieve a variable reference from its name. The way to do it is by running import sys and then getattr(sys.modules[__name__], FUNCTION_NAME) . It will retrieve the variable for you from the global scope. For example, if you have already defined a function called myfunc, then you can do f = getattr(sys.modules[__name__], 'myfunc'). Then you can call the function from your variable: f(). It will call the function myfunc(). Commented Oct 13, 2021 at 10:17
  • 1
    a suggestion - don't use str as a variable. Thank you Commented Oct 13, 2021 at 10:20
  • 1
    @Mahrkeenerh very true. >>> str(4) ; '4' ; >>> str = 'blalsd' ; >>> str(4) ; Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'str' object is not callable Commented Oct 13, 2021 at 10:21
  • 1
    Coincidentally, this example illustrates how function names are just like other variables in Python Commented Oct 13, 2021 at 10:26

1 Answer 1

4

With this example:

def my_func1():
    print("ONE")

def my_func2():
    print("TWO")

You can try eval, but it's not a good practise: (explanation)

eval("my_func1")()

Or you can assign this function to a string equivalent (inside a dictionary), and run that:

my_func_dict = {
    "my_func1": my_func1, 
    "my_func2": my_func2
}

my_func_dict["my_func1"]()

Both of these examples will print ONE.

Or closer to your example:

a = [my_func1, my_func2]

matches = [x for x in a if x.__name__ in str]

# matches now has two funcions inside, so you can run either:
matches[0]()
matches[1]()
Sign up to request clarification or add additional context in comments.

4 Comments

"You can't directly do: run("my_func")" this is false, you can do eval("my_func")() or similar
that's on me, wasn't aware of this. I'll edit the answer.
You can use the __name__ attribute. Put callables in the list and change matches = [x for x in a if x in str] to matches = [x for x in a if x.__name__ in str]
Using eval can be unsafe and dangerous depending on the string's source. If the input comes from a user form, someone could enter (lambda: print('I do something evil!')) which can be executed with eval("(lambda: print('I do something evil!'))")(). There are other reasons why you should avoid eval: stackoverflow.com/a/1832957/42659

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.