3

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)
9
  • While not important for the answer to the question, the use case is that I'm using an API which for each line of code will make a request to a server. I want to minimize the number of requests and so want to chain functions. But, I do not know at the outset the number of times I wish to chain the functions. Commented Jun 18, 2019 at 18:54
  • how does fn looks like? Commented Jun 18, 2019 at 18:54
  • You could use a recursive function with a counter and set the counter either manually or with an exit condition Commented Jun 18, 2019 at 18:55
  • how does fn looks like? @Ian also do they change every time? Commented Jun 18, 2019 at 18:57
  • To add more detail to the problem statement: I'm using the Python wrapper for Gremlin. The object is a vertex, and the fn function definition is property(name, value), which assigns a new property to that vertex in a graph. When the line of code executes, it sends the query to a Gremlin server and updates the specified vertex with a new property-value. (but all this is abstracted away) Commented Jun 18, 2019 at 19:03

1 Answer 1

4

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
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.