Search code examples
pythonchaining

Python function chaining an unknown number of times


Is there a way in Python to chain the same function an unknown number of times on an object?

For example. If I wanted to chain the function fn on the object obj twice I'd have:

obj.fn(**kwargs1).fn(**kwargs2)

If I wanted to chain a fn five times I'd have:

obj.fn(**kwargs1).fn(**kwargs2).fn(**kwargs3).fn(**kwargs4).fn(**kwargs5)

Solution

  • You can actually use a simple for loop, which iterates over the list of arguments, and applies each argument to the object, and reassign the results back to the object

    for args in list_of_args:
    
        obj = obj.fn(*args)
    

    For example, I can use this logic to chain string.replace as follows

    obj = 'aaaccc'
    list_of_args = [['a','b'], ['c','d']]
    
    for args in list_of_args:
        obj = obj.replace(*args)
    
    print(obj)
    

    And the output will be

    bbbddd
    

    Which is the same as doing 'aaabbb'.replace('a','b').replace('c','d')

    Or we can also perhaps use a recursive method, which takes in the object, and a counter which serves as an index of the current argument to be applied, and a number of times the function needs to run

    #fn is either defined, or imported from outside
    def chain_func(obj, counter, max_count):
    
        #If counter reaches max no of iterations, return
        if counter == max_count:
            return obj
    
        #Else recursively apply the function
        else:
            return chain_func(obj.fn(list_of_args[counter]), counter+1, max_count)
    
    #To call it twice
    list_of_args = [kwargs1, kwargs2]
    chain_func(obj, 0, 2)
    

    For example, I can use this logic to chain string.replace as follows

    def chain_func(obj, counter, max_count):
    
        #If counter reaches max no of iterations, return
        if counter == max_count:
            return obj
    
        #Else recursively apply the function
        else:
            return chain_func(obj.replace(*list_of_args[counter]), counter+1, max_count)
    
    
    list_of_args = [['a','b'], ['c','d']]
    print(chain_func('aaaccc', 0, 2))
    

    And the output will be

    bbbddd