Python使用getattr调用带有可变参数的函数

30

我正在使用getattr来根据变量调用不同的函数。

我正在做类似于以下的事情:

getattr(foo, bar) ()

这样做是可以的,像foo.bar()这样调用函数。

我的问题是我有'bar'函数并且我想使用不同的参数调用它。例如:

def f1() :
  pass

def f2(param1) :
  pass

def f3(param1,param2) :
  pass
所以“bar”可以是f1、f2或f3。 我尝试了这个: 假设params是一个包含“bar”函数所需所有参数的列表。
getattr(foo, bar) (for p in params :)

我希望得到一种“干净”的解决方案,不需要观察params变量的长度

3个回答

38

你可以尝试类似以下的方法:

getattr(foo, bar)(*params)

如果params是列表或元组,则此方法有效。将按顺序展开params中的元素:

params=(1, 2)
foo(*params)

等价于:

params=(1, 2)
foo(params[0], params[1])
如果有关键字参数,你也可以这样做。
getattr(foo, bar)(*params, **keyword_params)

其中keyword_params是一个字典。

此外,这个答案与getattr无关。它适用于任何函数/方法。


3
我知道OP没有特别提到,但我建议加上 **kwargs,这样他以后如果尝试使用关键字参数时就不会遇到难以追踪的错误。 - Silas Ray

7
这在Python 3中非常简单。以下是示例:
class C:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def m(self, x):
        print(f"{self.name} called with param '{x}'")
        return

ci = C("Joe", 10)
print(C)
print(ci)
print(C.m)
print(ci.m)
print(getattr(ci,'m'))
getattr(ci,'m')('arg')

<class '__main__.C'>
<__main__.C object at 0x000001AF4025FF28>
<function C.m at 0x000001AF40272598>
<bound method C.m of <__main__.C object at 0x000001AF4025FF28>>
<bound method C.m of <__main__.C object at 0x000001AF4025FF28>>
Joe called with param 'arg'

请注意,getattr 函数是来自于 builtins 模块,在本例中使用两个参数,即类实例 ci 和表示函数名的字符串。
我们还可以为参数定义默认值。
def m(self, x=None):
    print(f"{self.name} caled with param '{x}'")
    return

在哪种情况下我们可以称之为:
getattr(ci,'m')()

这对我很有帮助。我的理解是:getattr(object_on_which_the_function_is_to_be_called, function_name_as_a_string)(parameters_to_be_passed_to_the_function)。这将导致一个函数调用function_name_as_a_string(parameters_to_be_passed_to_the_function)。不确定我的理解是否非常正确,但它起作用了,这就是我的理解方式。 - manpikin
@manpikin 我认为你的意思是第一个参数应该是“调用函数的对象来自”,而不是“在”。 你需要给函数提供一个对象名称和一个属性名称作为字符串,它会尝试返回对象属性的值(如果存在)。如果不存在,你可以给它第三个参数,即默认值。 - BUFU
谢谢@prosti。这对我很有用。只需简单调用'getattr(Object instance,methodName in String)(parameters)即可。太棒了! - chaatna

1

也许更易读的方式,对于处理异常来说更好:

class foo:
    def method_xy(self, *args, **kwargs):
        print(f'args:{args}, kwargs:{kwargs}')


bar = 'method_xy'
xi = foo()
try:
    func_name = getattr(xi, bar)
except AttributeError:
    # handle missing method
    pass

args = ['bla1', 'bla2']
kwargs = {'a1': 1, 'a2': 2}

try:
    result = func_name(*args, **kwargs)
except TypeError:
    # handle Problems with arguments
    pass

这比 getattr(ci,'m')() 更难阅读和理解。 - user19322455

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接