MethodChain

Miles semanticist at gmail.com
Sun Jul 20 09:18:55 CEST 2008


On Sun, Jul 20, 2008 at 1:01 AM, Marc 'BlackJack' Rintsch
<bj_666 at gmx.net> wrote:
> The methods are a problem IMHO.  You can't add an own method/function with
> the name `fire()` or `toFunction()`.  `MethodChain` has to know all
> functions/methods in advance.  You can add the methods of whole classes at
> once and there are over 300 pre-added, this begs for name clashes.

Name clashes aren't an issue, since MethodChain doesn't apply any
special meaning to the method names it knows; the limitation is
because JavaScript doesn't allow you to modify property lookup
behavior.  And since we can make the chain object callable, we don't
need "fire" or "toFunction" methods.

###########

from functools import partial

class MethodChain(object):
    # The implementation of this could be cleaner.  I would prefer
    # chain.foo() to return a new object instead of modifying chain.
    # But this is easier to write and closer to the JavaScript implementation.
    def __init__(self):
        self._methodname = None
        self._chain = []

    def __getattr__(self, methodname):
        assert self._methodname is None
        self._methodname = methodname
        return self

    def __call__(self, *args, **kwargs):
        if self._methodname is None:
            assert len(args) == 1 and not kwargs
            result = args[0]
            for method in self._chain:
                result = getattr(result, method[0])(*method[1], **method[2])
            return result
        else:
            self._chain.append((self._methodname, args, kwargs))
            self._methodname = None
            return self

def compose(*callables):
    def composition(arg):
        result = arg
        for callable in callables:
            # or should that be reversed(callables)? to be mathematically
            # accurate, yes, probably; however, it also makes sense to
            # specify the callables in the order they'll be applied
            result = callable(result)
        return result
    return composition

chain = MethodChain().lower().replace('ello,', 'ey').title().split()

print chain('HELLO, world')

func = compose(chain, partial(map, lambda s: s+'!'), ' '.join)

print func('HELLO, world')

###########

-Miles



More information about the Python-list mailing list