Search code examples
pythonfunctiongetattr

Python Data Enrichment - Calling functions based on Name-String with getattr


This is a little tutorial that I find very useful. It is a compilation of many questions that you can find here for example. I have tried to apply it to a real-world scenario to make it easier to understand.


Let's imagine for a second that we have a dataset that we want to enrich. To do so we subdivide the data in groups and on each group we need to apply a different function. There are many ways to do this.

One of the ways is to call a function based on a name. Here we have class Test that can call foo and bar.
Note: foo and bar could also be methods of Test

While outside the the class we could call the method directly:

def foo(s="Nothing"):
    print("this is foo")
    print("\"{}\" was given as arg".format(s))
    
def bar(s="Nothing"):
    print("this is bar")
    print("\"{}\" was given as arg".format(s))

class Test():
    def __init__(self):
        self.a = foo
        self.b = bar

t = Test()

t.a("Hello World")

This results in:

>>> this is foo
>>> "Hello World" was given as arg

But what would you do if the method you have to call depends on the group your data belongs to ? We could have 2 groups: one and two.

Well then you could create a conditional loop... like so:

group = "one"
if group == "one":
    t.a("Hello World")
else:
    t.b("Hello Moon")

Great, that works !

Let's now imagine that we have over 50 possible groups our data can belong to ...
Can you imagine the code with 50 if ... else if statements ?


Solution

  • The option above would be pretty unreadable. Which is why it can be useful to have a way to call a function based on a Name as a string.
    Here is one way to do it:

    Create one single dictionary that keeps the different functions that need to be applied to each group.

    function_dict = {
        "one": "a",
        "two": "b"
    }
    

    Then we use the getattr built-in function call the function depending on the group:

    def launchFunction(blah):
        getattr(t, function_dict[blah])("This Works Too")
    

    This allows us to call foo or bar based on the function_dict key:

    launchFunction("two")
    

    This would result in:

    >>> this is bar
    >>> "This Works Too" was given as arg
    

    I hope that this will be useful to someone.
    Feel free to comment.