Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: jQuery-like function chaining?

I couldn't find anything on this subject on Google, so I think I should ask it here:

Is it possible to chain functions with Python, like jQuery does?

['my', 'list'].foo1(arg1, arg2).foo2(arg1, arg2).foo3(arg1, arg2) #etc...

I am losing a lot of space and readability when I write this code:

foo3(foo2(foo1(['my', 'list'], arg1, arg2), arg1, arg2), arg1, arg2) #etc...

There seems to exist some illusive library for creating such functions, but I can't seem to see why this has to be so complicated-looking...

Thanks!

like image 494
Blender Avatar asked Dec 03 '10 06:12

Blender


People also ask

Can you chain jQuery functions?

With jQuery, you can chain together actions/methods. Chaining allows us to run multiple jQuery methods (on the same element) within a single statement.

What is method chaining in Python?

Method chaining is a programmatic style of invoking multiple method calls sequentially with each call performing an action on the same object and returning it. It eliminates the cognitive burden of naming variables at each intermediate step.

Which function is used to chain animation?

jQuery | chaining() With jQuery, we can use do chaining which means to chain together multiple methods in a single statement on a single element.


2 Answers

As long as the function returns a value, you can chain it. In jQuery, a selector method usually returns the selector itself, which is what allows you to do the chaining. If you want to implement chaining in python, you could do something like this:

class RoboPuppy:

  def bark(self):
    print "Yip!"
    return self

  def growl(self):
    print "Grr!"
    return self

pup = RoboPuppy()
pup.bark().growl().bark()  # Yip! Grr! Yip!

Your problem, however, seems to be that your function arguments are too cramped. Chaining is not a solution to this. If you want to condense your function arguments, just assign the arguments to variables before passing them to the function, like this:

spam = foo(arg1, arg2)
eggs = bar(spam, arg1, arg2)
ham = foobar(eggs, args)
like image 99
camel_space Avatar answered Sep 27 '22 20:09

camel_space


Here's an expansion of Simon's ListMutator suggestion:

class ListMutator(object):

    def __init__(self, seq):
        self.data = seq

    def foo1(self, arg1, arg2):
        self.data = [x + arg1 for x in self.data]
        # This allows chaining:
        return self

    def foo2(self, arg1, arg2):
        self.data = [x*arg1 for x in self.data]
        return self

if __name__ == "__main__":
    lm = ListMutator([1,2,3,4])
    lm.foo1(2, 0).foo2(10, 0)
    print lm.data

    # Or, if you really must:
    print ListMutator([1,2,3,4]).foo1(2, 0).foo2(10, 0).data

You could go one better and make ListMutator act entirely like a list by using the collections abstract base classes. In fact, you could subclass list itself, although it may restrict you from doing certain things you might need to do... and I don't know what the general opinion is on subclassing built-in types like list.

like image 31
detly Avatar answered Sep 27 '22 19:09

detly