如何使用带有函数名称的字符串调用函数?例如:
import foo
func_name = "bar"
call(foo, func_name) # calls foo.bar()
如何使用带有函数名称的字符串调用函数?例如:
import foo
func_name = "bar"
call(foo, func_name) # calls foo.bar()
当前回答
给定一个字符串和一个函数的完整python路径,这就是我如何获得所述函数的结果:
import importlib
function_string = 'mypackage.mymodule.myfunc'
mod_name, func_name = function_string.rsplit('.',1)
mod = importlib.import_module(mod_name)
func = getattr(mod, func_name)
result = func()
其他回答
虽然getattr()是一种优雅的(大约快7倍)方法,但您可以使用eval从函数(local、class方法、模块)获得返回值,其优雅程度与x=eval('fo.bar')()相同。当您实现一些错误处理时,就会非常安全(getattr也可以使用相同的原理)。模块导入和类示例:
# import module, call module function, pass parameters and print retured value with eval():
import random
bar = 'random.randint'
randint = eval(bar)(0,100)
print(randint) # will print random int from <0;100)
# also class method returning (or not) value(s) can be used with eval:
class Say:
def say(something='nothing'):
return something
bar = 'Say.say'
print(eval(bar)('nice to meet you too')) # will print 'nice to meet you'
当模块或类不存在(键入错误或其他更好的错误)时,就会引发NameError。如果函数不存在,则引发AttributeError。这可用于处理错误:
# try/except block can be used to catch both errors
try:
eval('Say.talk')() # raises AttributeError because function does not exist
eval('Says.say')() # raises NameError because the class does not exist
# or the same with getattr:
getattr(Say, 'talk')() # raises AttributeError
getattr(Says, 'say')() # raises NameError
except AttributeError:
# do domething or just...
print('Function does not exist')
except NameError:
# do domething or just...
print('Module does not exist')
值得一提的是,如果您需要将函数(或类)名称和应用程序名称作为字符串传递,那么可以这样做:
myFnName = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn = getattr(app,myFnName)
在python3中,可以使用__getattribute__方法。请参见以下列表方法名称字符串示例:
func_name = 'reverse'
l = [1, 2, 3, 4]
print(l)
>> [1, 2, 3, 4]
l.__getattribute__(func_name)()
print(l)
>> [4, 3, 2, 1]
基于Patrick的解决方案,要动态获取模块,请使用以下方法导入:
module = __import__('foo')
func = getattr(module, 'bar')
func()
我以前也遇到过类似的问题,那就是将字符串转换为函数。但我不能使用eval()或ast.literal_eval(),因为我不想立即执行这段代码。
例如,我有一个字符串“foo.bar”,我想将它指定给x作为函数名,而不是字符串,这意味着我可以在DEMAND上通过x()调用函数。
这是我的代码:
str_to_convert = "foo.bar"
exec(f"x = {str_to_convert}")
x()
至于您的问题,您只需要添加模块名foo和。在{}之前,如下所示:
str_to_convert = "bar"
exec(f"x = foo.{str_to_convert}")
x()
警告!!!eval()或exec()是一种危险的方法,您应该确认其安全性。警告!!!eval()或exec()是一种危险的方法,您应该确认其安全性。警告!!!eval()或exec()是一种危险的方法,您应该确认其安全性。