What's the way to call a function dynamically in Python?
I would like to do something like:
dct = ['do_this', 'do_that']
dct[0]() //开发者_JAVA百科 call do_this
But you can't call the string as a function (will get an error).
How can I achieve this without switching and without using a list of lambdas or functions?
Explicitly I want to refer the function by name.
Functions are first-class objects in Python:
def do_this():
pass
def do_that():
pass
dct = [do_this, do_that]
dct[0]() # calls do_this()
If dct
absolutely has to be a list of strings, I'd go with eval()
:
eval(dct[0] + "()")
It's not pretty, but switching between globals()
and getattr()
on the proper module can be a pain.
Functions are first class objects. So like this:
def do_this():
print "In do_this"
def do_that():
print "In do_that"
dct = [do_this, do_that]
dct[0]()
If you really want to call them from a string list you can use globals():
dct = ['do_this', 'do_that']
globals()[dct[0]]()
But I would suggest that using globals() (or locals()) probably isn't the right way to solve your problem. Grok the python way: >>> import this
You can use getattr
if they are in a module or globals()
if they are in the global namespace:
dct = ['do_this', 'do_that']
getattr(my_module, dct[0])()
globals()[dct[0]]()
If the functions you want to call are part of a module:
import module
getattr(module, funcname_string)(*args, **kwargs)
As others have said, functions in Python are first-class objects. If you really want to get their names from a list, you can either use eval()
(not popular) or use the globals()
dictionary. Keep in mind that if these strings come from users, they're pretty dangerous. And if they don't come from users, then don't use strings.
having the functions in some dict or in a class or instance
def fn_a():
pass
some_dict = {
'fn_a': fn_a,
}
class Someclass(object):
@classmethod
def fn_a(cls):
pass
# normal instance method
def fn_b(self):
pass
some_instance = Someclass()
you could do: some_dict['name']()
or getattr(some_instance, 'fn_b')()
or getattr(Someclass, 'fn_a')()
def do_this(): pass
def do_that(): pass
dct = dict((x.__name__, x) for x in [do_this, do_that])
# dct maps function names to the function objects
# the names *don't* have to match the function name in your source:
# dct = {"foo": do_this}
# which means user-facing names can be anything you want
dct["do_this"]() # call do_this
Use getattrs()
dct = ['do_this', 'do_that']
getattr(class_object, dct[0])()
You can also dynamically call functions within classes via
inspect.getmembers(my_class, predicate=inspect.ismethod)
Then do a for loop and call getattr(class, methodname)
I think using getattr is more better suited for most cases, than using globals(). Globals() uses the global namespace scope of the entire program which may cause scope problems down the road.
To call the function dynamically which is defined in the same module, you can do this way:
import sys
## get the reference to the current module - key trick to get the ref to same module
this = sys.modules[__name__]
def foo():
msg="I'm called dynamically!"
return msg
## `fname` can be taken as an input from the user
fname='foo'
## get the reference to the function from the module
fn = getattr(this, fname)
## make the function call
fn()
精彩评论