[Python-Dev] Shortcut Notation for Chaining Method Calls

Michael O'Keefe mokeefe at okeefecreations.com
Sat Feb 3 18:36:10 CET 2007


I had an idea on some new functionality I'd like to see offered
in the python object class. I did some searching on the list 
but I wouldn't doubt that someone has proposed something 
like this before as chaining method calls seems like something 
folks would want to do.

Specifically, I'd like to see a built-in shorthand to allow me to 
chain method calls even when a method call does not explicity 
return a reference to the instance of the object (self).

I have an example below. In this example, someFunc represents 
the current way of dealing with calling methods that modify an
object's state with no return value (if you found yourself doing 
this a lot, you might just write a wrapper function).

The function explicitReturn shows how things might go if python
implicitly returned self when no other return value was specified
(similar to Ruby). I'm not proposing this, but have included it for 
completeness.

The final two functions give some options for what I'm proposing
as a shorthand (ideally included in class object but used in a 
subclass of class list in this example). The first of the two functions, 
newFunc01, defines the method "_". I'm not crazy about this 
because it's not very descriptive but it is the shortest way I could
think of.

The second possible shorthand is in, newFunc02, which defines
the method "self_". I didn't want the method to be too long but my
intent was "apply the given method and return self". I used the trailing
underscore so as not to confuse with the self instance variable.

I'm sure there are other ways to do this as well but what do people
think? Has something like this come up before?

def someFunc():
    a = list([8,9,7,1])
    a.sort()
    a.reverse()
    a.pop(0)
    return a

def explicitReturn():
    a = ExplicitReturnList([8,9,7,1]).sort().reverse()
    a.pop(0)
    return a

def newFunc01():
    return NewList([8,9,7,1])._('sort')._('reverse')._('pop',0)

def newFunc02():
    return NewList([8,9,7,1]).self_('sort').self_('reverse').self_('pop',0)

class NewList(list):
    def __init__(self,*args,**kwargs):
        list.__init__(self,*args,**kwargs)
    def _(self,methodName,*args,**kwargs):
        method = getattr(self,methodName)
        method(*args,**kwargs)
        return self
    def self_(self,methodName,*args,**kwargs):
        method = getattr(self,methodName)
        method(*args,**kwargs)
        return self

class ExplicitReturnList(list):
    def __init__(self,*args,**kwargs):
        list.__init__(self,*args,**kwargs)
    def sort(self):
        super(ExplicitReturnList,self).sort()
        return self
    def reverse(self):
        super(ExplicitReturnList,self).reverse()
        return self

print someFunc()        # returns [8, 7, 1]
print explicitReturn()  # returns [8, 7, 1]
print newFunc01()       # returns [8, 7, 1]
print newFunc02()       # returns [8, 7, 1]



More information about the Python-Dev mailing list