Path: csiph.com!usenet.pasdenom.info!news.etla.org!news.stack.nl!newsfeed.xs4all.nl!newsfeed4.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'else:': 0.03; 'value,': 0.04; 'cpython': 0.05; 'none:': 0.07; '"__main__":': 0.09; '*args,': 0.09; '__name__': 0.09; 'obj': 0.09; 'omit': 0.09; "people's": 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'url:activestate': 0.09; 'python': 0.11; 'def': 0.12; 'missed': 0.12; '3.3,': 0.16; 'ironpython': 0.16; 'name)': 0.16; 'name):': 0.16; 'received:80.91.229.3': 0.16; 'received:dip0.t-ipconnect.de': 0.16; 'received:plane.gmane.org': 0.16; 'received:t-ipconnect.de': 0.16; 'recipe': 0.16; 'self.obj': 0.16; 'wrote:': 0.18; 'code.': 0.18; 'discussion': 0.18; 'work,': 0.20; 'header:User-Agent:1': 0.23; 'header:X-Complaints-To:1': 0.27; 'feature': 0.29; 'url:code': 0.29; "doesn't": 0.30; '3.2': 0.31; "d'aprano": 0.31; 'steven': 0.31; 'class': 0.32; 'style': 0.33; 'skip:_ 10': 0.34; 'classes': 0.35; 'but': 0.35; 'method': 0.36; 'list': 0.37; 'to:addr:python-list': 0.38; 'rather': 0.38; 'ability': 0.39; 'to:addr:python.org': 0.39; 'received:org': 0.40; 'chain': 0.60; 'most': 0.60; 'further': 0.61; 'here': 0.66; 'details,': 0.68; 'equals': 0.68; 'frequently': 0.68; 'self.value': 0.84 X-Injected-Via-Gmane: http://gmane.org/ To: python-list@python.org From: Peter Otten <__peter__@web.de> Subject: Re: Method chaining Date: Fri, 22 Nov 2013 13:08:03 +0100 Organization: None References: <528f3f4e$0$29992$c3e8da3$5496439d@news.astraweb.com> Mime-Version: 1.0 Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7Bit X-Gmane-NNTP-Posting-Host: p5084aa86.dip0.t-ipconnect.de User-Agent: KNode/4.7.3 X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 68 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1385122060 news.xs4all.nl 15975 [2001:888:2000:d::a6]:47817 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:60216 Steven D'Aprano wrote: > A frequently missed feature is the ability to chain method calls: > > x = [] > x.append(1).append(2).append(3).reverse().append(4) > => x now equals [3, 2, 1, 4] > > > This doesn't work with lists, as the methods return None rather than > self. The class needs to be designed with method chaining in mind before > it will work, and most Python classes follow the lead of built-ins like > list and have mutator methods return None rather than self. > > Here's a proof-of-concept recipe to adapt any object so that it can be > used for chaining method calls: > > > class chained: > def __init__(self, obj): > self.obj = obj > def __repr__(self): > return repr(self.obj) > def __getattr__(self, name): > obj = getattr(self.obj, name) > if callable(obj): > def selfie(*args, **kw): > # Call the method just for side-effects, return self. > _ = obj(*args, **kw) > return self > return selfie > else: > return obj > > > chained([]).append(1).append(2).append(3).reverse().append(4) > => returns [3, 2, 1, 4] > > > Tested, and works, in CPython 2.4 through 2.7, 3.2 and 3.3, Jython 2.5, > and IronPython 2.6. > > See here for further discussion of the limitations: > > http://code.activestate.com/recipes/578770-method-chaining/ Here's my take: class Chained(object): def __init__(self, value, method=None): self.value = value self.method = method def __call__(self, *args, **kw): result = self.method(*args, **kw) if result is None: result = self.value return Chained(result) def __getattr__(self, name): return Chained(self.value, getattr(self.value, name)) if __name__ == "__main__": print(Chained([]).append(1).append(2).append(3).reverse().append(4).value) print(Chained([]).append(1).extend([2,1,1]).count(1).value) These things are nice to write as long as you omit the gory details, but personally I don't want to see the style it favours in my or other people's code.