This can be done with an external wrapper, so it might be possible to do this with MacroPy. It absolutely must be a compact notation, though.
Something like: merged = c[ my_dict.update(dict_a).update(dict_b) ] Desugaring into # top-level somewhere elsedef fresh_name(x, *args): y = x for op, a, kw in args: y = getattr(y, op)(*a, **kw) y = x if y is None else y return y merged = fresh_name(my_dict, ("update", [dict_a], {}), ("update", [dict_b], {})) could be doable pretty easily, and is flexible enough to make old-school chaining work while also letting things that return None do the right thing. If you don't want to use macros, an alternative could be doing something like: chain(my_dict).update(dict_a).update(dict_b).get Using a wrapper as Steven mentioned. On Fri, Feb 21, 2014 at 5:13 PM, Steven D'Aprano <steve@pearwood.info>wrote:
On Sat, Feb 22, 2014 at 04:30:03AM +1100, Chris Angelico wrote:
Yeah, I'm insane, opening another theory while I'm busily championing a PEP.
Completely raving bonkers :-)
In Python, as in most languages, method chaining requires the method to return its own object. [...]
Rather than add syntactic support for this, I'd prefer a wrapper in the standard library. Syntax implies to me that chaining operators is, in some sense, a preferred idiom of the language, and although method chaining is sometimes useful, I don't think that it ought to be preferred. There's a difference between "Python supports this, use this syntax" and "You can do this in Python, import this library and call this function to make it happen".
[...]
So here's the proposal. Introduce a new operator to Python, just like the dot operator but behaving differently when it returns a bound method. We can possibly use ->, or maybe create a new operator that currently makes no sense, like .. or .> or something. Its semantics would be:
1) Look up the attribute following it on the object, exactly as per the current . operator 2) If the result is not a function, return it, exactly as per current. 3) If it is a function, though, return a wrapper which, when called, calls the inner function and then returns self.
When you say "a function", do you actually mean a function? What about other callables, such as methods (instance, class or static) or types? How does this interact with the descriptor protocol?
This can be done with an external wrapper, so it might be possible to do this with MacroPy. It absolutely must be a compact notation, though.
Here's an alternative: add a `chained` wrapper to, oh, let's say functools (I don't think it needs to be a built-in). In my hierarchy of language preferredness, this suggests that while Python *supports* method chaining, it isn't *preferred*. (If it were preferred, it would happen by default, or there would be syntax for it.) If you want to chain methods, you can, but it's a slightly unusual thing to do, and the fact that you have to import a module and call a wrapper class should be sufficient discouragement for casual (ab)use.
Inspired by the Ruby "tap" method, I wrote this proof-of-concept last year:
https://mail.python.org/pipermail/python-list/2013-November/660892.html
http://code.activestate.com/recipes/578770-method-chaining/
Of course, if the class author wants to support method chaining, they can always write the methods to return self :-)
-- Steven _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/