[Tutor] function algebra (was: Re: Python vs. Ruby)

Abel Daniel abli at freemail.hu
Fri Oct 31 09:48:00 EST 2003


[ me, a bit earlier: ]
> Finishing up (adding other stuff from
> http://python.org/doc/current/ref/numeric-types.html
> and handling things like "Fun(math.sin) + 5" ) are left as an exercise
> to the reader. :)
I couldn't stand not doing it :)
It's a bit less readable, but should handle any numerical operation.
It also handles the case of "f=Fun(math.sin) + 5" (so that in this case
f(x) will be math.sin(x) + 5), plus it does composition:

>>> cos=Fun(math.cos)
>>> cs = cos.compose(math.sin)
>>> cs(1)
0.66636674539288054
>>> math.cos(math.sin(1))
0.66636674539288054
>>> 

------8<-------------
# we don't need to add __iadd__ and such as those fall back to using
# __add__ etc.
unary_operators=['__neg__', '__pos__', '__abs__', '__invert__',
                 '__complex__', '__int__', '__long__', '__float__',
                 '__oct__', '__hex__']
binary_operators=['__add__','__sub__','__mul__', '__floordiv__',
                  '__mod__', '__divmod__', '__lshift__', '__rshift__',
                  '__and__', '__xor__', '__or__', '__radd__',
                  '__rsub__', '__rmul__', '__rdiv__', '__rtruediv__',
                  '__rfloordiv__', '__rmod__', '__rdivmod__',
                  '__rpow__', '__rlshift__', '__rrshift__',
                  '__rand__', '__rxor__', '__ror__']
ternary_operators=['__pow__']

class Fun:
    def __init__(self, func):
        self.func=func

    def __call__(self, *a, **kw):
        return self.func(*a, **kw)

    def compose(self, other):
        def f(*a, **kw):
            return self.func(other(*a, **kw))
        return Fun(f)

    def __getattr__(self, name):
        if name in binary_operators:
            return self.binary_operation(name)
        elif name in unary_operators:
            return self.unary_operation(name)
        elif name in ternary_operators:
            return self.ternary_operation(name)
        else:
            raise AttributeError

    def binary_operation(self, name):
        def ff(other):
            def f(*a, **kw):
                return getattr(self.func(*a, **kw), name)(other(*a, **kw))
            return Fun(f)
        return ff

    def unary_operation(self, name):
        def ff():
            def f(*a, **kw):
                return getattr(self.func(*a, **kw), name)()
            return Fun(f)
        return ff

    def ternary_operation(self, name):
        def ff(other, *args):
            def f(*a, **kw):
                return getattr(self.func(*a, **kw), name)(other(*a, **kw),
                                                          *args)
            return Fun(f)
        return ff

    def __coerce__(self, other):
        if callable(other):
            return self, other
        else:
            return self, lambda x: other

-----------8<-------------------

-- 
Abel Daniel



More information about the Tutor mailing list