Python using getattr to call function with variable parameters
Asked Answered
B

3

30

I'm using getattr to call different functions depending on a variable.

Im doing something like that:

getattr(foo, bar) ()

That works, calling functions like foo.bar()

My problem is that I have 'bar' functions and I want to call it with different parameters. For example:

def f1() :
  pass

def f2(param1) :
  pass

def f3(param1,param2) :
  pass

so 'bar' could be f1, f2, or f3

I tried this: assumming that params is a list which contains all parameters needed for the 'bar' function

getattr(foo, bar) (for p in params :)

I watching for a "clean" solution, with no needed to watch the length on the params variable

Becnel answered 2/8, 2012 at 15:51 Comment(0)
M
38

You could try something like:

getattr(foo, bar)(*params)

This works if params is a list or a tuple. The elements from params will be unpacked in order:

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

is equivalent to:

params=(1, 2)
foo(params[0], params[1])

If there are keyword arguments, you can do that too.

getattr(foo, bar)(*params, **keyword_params)

where keyword_params is a dictionary.

Also, This answer is really independent of getattr. It will work for any function/method.

Martinic answered 2/8, 2012 at 15:53 Comment(1)
I know OP didn't ask specifically, but I'd add **kwargs too, just so he doesn't end up with hard to track down bugs later on should he attempt to use keyword arguments.Jene
D
7

This is very simple in Python 3. Here is the example:

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'

Note that getattr is from the builtins module, takes in our case the two parameters, the class instance ci and the string representing the name of the function.

We could also define the defult value for the parameter.

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

In which case we may call:

getattr(ci,'m')()
Doorpost answered 24/5, 2019 at 14:16 Comment(3)
This helped me. I understood it like... getattr(object_on_which_the_function_is_to_be_called, function_name_as_a_string)(parameters_to_be_passed_to_the_function). This will result into a function call function_name_as_a_string(parameters_to_be_passed_to_the_function). Not sure if my understanding is very correct, but it worked and that's how I perceived it..Harwood
@Harwood I think you mean the first argument should be "object from which the function is to be called", not "on". You give the function an object name and an attribute name as a string and it tries to give you back the value of the object's attribute, if existing. If not, you can give it the third argument, a default value.Airs
Thank you @prosti. It worked for me. Just simple call 'getattr(Object instance, methodName in String)(parameters) AwesomeCrab
I
1

A maybe more readable way, which is better for handling exceptions:

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
Inanition answered 22/1, 2020 at 15:53 Comment(1)
This is much harder to read and understand than getattr(ci,'m')()Purlin

© 2022 - 2024 — McMap. All rights reserved.