invoking multiple methods (Was: Python vs. Ruby)

Bengt Richter bokr at oz.net
Fri Jan 10 00:04:50 CET 2003


On Thu, 09 Jan 2003 15:57:38 GMT, Mike Meyer <mwm at mired.org> wrote:

>Erik Max Francis <max at alcyone.com> writes:
>
>> "Stuart D. Gathman" wrote:
>> >   aList.sort();.reverse()       # aList.sort(); aList.reverse()
>> > A statement cannot begin with '.', so ';.' means to invoke another
>> > method
>> > on the same object.
>> But is this awkwardness really worth it?  One of Python's truly great
>> assets is its transparently readable code.  I'm opposed on general
>> principle to anything which defeats that.
>
>True. However, the idea of specifying multiple methods on the same
>object is consistent with recent changes (op=, for instance), and
>seems useful enough to be worth writing a PEP for - *if* a readable
>syntax can be invented for it.
>
>I don't like ;.. I'm not sure I like the idea of tweaking the
>semantics of statement at all. Maybe something like:
>
>        aList.(sort(), reverse())
>
>Almost like using a tuple as the method, and it does all the
>invocations in the tuple. Except it isn't a real tuple, because the
>methods aren't reall calls.

I'd rather reserve the xxx.(something) syntax for an alternate spelling
of getattr(xxx, something), where something is an expression resulting in a string.
E.g.,
    for name in dir(thing):    # when you want more than vars(thing).items()
        print name, thing.(name)

Or maybe .( xxx ). for xxx special effects at the tokenizer level ;-)

How about getting your parens without a dot, using __call__ and passing bound methods?

 >>> class L(list):
 ...     def __call__(self, *ops):
 ...         for op in ops:
 ...            op()
 ...         return self
 ...
 >>> a = L([3,1,2])
 >>> a(a.sort, a.reverse)
 [3, 2, 1]
 >>> a
 [3, 2, 1]
 >>> a(a.reverse) + [4]
 [1, 2, 3, 4]
 >>> a
 [1, 2, 3]
 >>> a(a.reverse) + [4]
 [3, 2, 1, 4]

Alternatively:

 >>> class L2(list):
 ...     def __call__(self, *ops):
 ...         l = self[:]
 ...         for op in ops:
 ...            op(l)
 ...         return l
 ...
 >>> b = L2([3,1,2])
 >>> b
 [3, 1, 2]
 >>> b(list.reverse)
 [2, 1, 3]
 >>> b
 [3, 1, 2]
 >>> b(list.sort, list.reverse)
 [3, 2, 1]
 >>> b
 [3, 1, 2]

Looks nicer with some local bindings though:

 >>> sort = list.sort; reverse=list.reverse
 >>> b
 [3, 1, 2]
 >>> b(sort)
 [1, 2, 3]
 >>> b
 [3, 1, 2]
 >>> b(sort, reverse)
 [3, 2, 1]
 >>> b(reverse)
 [2, 1, 3]

Regards,
Bengt Richter




More information about the Python-list mailing list