在Python程序中,对于给定一个带有函数名称的字符串,调用函数的最佳方法是什么?例如,假设我有一个模块
我需要得到函数的返回值,这就是为什么我不只是使用
假设模块
1 2 3 | import foo method_to_call = getattr(foo, 'bar') result = method_to_call() |
到此为止,第2行和第3行可以压缩为:
1 | result = getattr(foo, 'bar')() |
如果这对您的用例更有意义的话。您可以以这种方式在类实例绑定方法、模块级方法、类方法上使用
1 | locals()["myfunction"]() |
或
1 | globals()["myfunction"]() |
局部变量返回一个带有当前本地符号表的字典。返回一个带有全局符号表的字典。
帕特里克的解决方案可能是最干净的。如果你也需要动态拾取模块,你可以这样导入:
1 2 3 | module = __import__('foo') func = getattr(module, 'bar') func() |
只是一个简单的贡献。如果我们需要实例化的类在同一个文件中,我们可以这样使用:
1 2 3 4 5 6 7 8 | # Get class from globals and create an instance m = globals()['our_class']() # Get the function (from the instance) that we need to call func = getattr(m, 'function_name') # Call it func() |
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 | class A: def __init__(self): pass def sampleFunc(self, arg): print('you called sampleFunc({})'.format(arg)) m = globals()['A']() func = getattr(m, 'sampleFunc') func('sample arg') # Sample, all on one line getattr(globals()['A'](), 'sampleFunc')('sample arg') |
如果不是一个类:
1 2 3 4 | def sampleFunc(arg): print('you called sampleFunc({})'.format(arg)) globals()['sampleFunc']('sample arg') |
给定一个字符串,一个完整的python路径的一个函数,这是我如何得到的结果说的函数:
1 2 3 4 5 6 | 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() |
根据Python编程常见问题解答,最好的答案是:
1 2 3 4 5 | functions = {'myfoo': foo.bar} mystring = 'myfoo' if mystring in functions: functions[mystring]() |
The primary advantage of this technique is that the strings do not need to match the names of the functions. This is also the primary technique used to emulate a case construct
答案(我希望)从来没有人想要
Eval等行为
1 | getattr(locals().get("foo") or globals().get("foo"),"bar")() |
为什么不添加自动导入呢
1 2 3 4 5 | getattr( locals().get("foo") or globals().get("foo") or __import__("foo"), "bar")() |
以防我们有多余的字典要查
1 2 3 4 5 | getattr(next((x for x in (f("foo") for f in [locals().get, globals().get, self.__dict__.get, __import__]) if x)), "bar")() |
我们需要更进一步
1 2 3 4 5 6 7 8 9 | getattr(next((x for x in (f("foo") for f in ([locals().get, globals().get, self.__dict__.get] + [d.get for d in (list(dd.values()) for dd in [locals(),globals(),self.__dict__] if isinstance(dd,dict)) if isinstance(d,dict)] + [__import__])) if x)), "bar")() |
值得注意的是,如果您需要将函数(或类)名和应用程序名作为字符串传递,那么您可以这样做:
1 2 3 4 | myFnName ="MyFn" myAppName ="MyApp" app = sys.modules[myAppName] fn = getattr(app,myFnName) |
试试这个。虽然这仍然使用eval,但它只使用eval从当前上下文调用函数。然后,您就可以随心所欲地使用真正的函数了。
对我来说,这样做的主要好处是,您将在调用函数时得到任何与值相关的错误。然后在调用时只会得到与函数相关的错误。
1 2 3 4 5 6 7 8 9 10 11 | def say_hello(name): print 'Hello {}!'.format(name) # get the function by name method_name = 'say_hello' method = eval(method_name) # call it like a regular function later args = ['friend'] kwargs = {} method(*args, **kwargs) |
这些建议对我都没有帮助。但我确实发现了这一点。
1 | <object>.__getattribute__(<string name>)(<params>) |
我使用的是python 2.66
希望这有助于
这个问题是关于如何使用方法名分配给一个变量[duplicate]来动态调用类中的方法,这个变量[duplicate]被标记为与这个变量相同的一个duplicate,我在这里发布了一个相关的答案:
场景是,一个类中的一个方法想要动态地调用同一个类上的另一个方法,我在原来的例子中添加了一些细节,提供了一些更广泛的场景和清晰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class MyClass: def __init__(self, i): self.i = i def get(self): func = getattr(MyClass, 'function{}'.format(self.i)) func(self, 12) # This one will work # self.func(12) # But this does NOT work. def function1(self, p1): print('function1: {}'.format(p1)) # do other stuff def function2(self, p1): print('function2: {}'.format(p1)) # do other stuff if __name__ =="__main__": class1 = MyClass(1) class1.get() class2 = MyClass(2) class2.get() |
Output (Python 3.7.x)
function1: 12
function2: 12