[Python-Dev] Function Operators
Thomas Jollans
thomas at jollans.com
Sun Jul 18 19:43:44 CEST 2010
On 07/18/2010 05:52 PM, Reid Kleckner wrote:
> Usual disclaimer: python-dev is for the development *of* python, not
> *with*. See python-list, etc.
Moving to python-list. Please keep discussion there.
>
> That said, def declares new functions or methods, so you can't put
> arbitrary expressions in there like type(f).__mul__ .
>
> You can usually assign to things like that though, but in this case
> you run into trouble, as shown below:
>
>>>> def func(): pass
> ...
>>>> type(func)
> <class 'function'>
>>>> def compose(f, g):
> ... return lambda x: f(g(x))
> ...
>>>> type(func).__mul__ = compose
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> TypeError: can't set attributes of built-in/extension type 'function'
>
> As the interpreter says, it doesn't like people mucking with operator
> slots on built in types.
>
> Finally, if you like coding in that very functional style, I'd
> recommend Haskell or other ML derived languages. Python doesn't
> support that programming style very well by choice.
>
> Reid
>
> On Sun, Jul 18, 2010 at 8:34 AM, Christopher Olah
> <christopherolah.co at gmail.com> wrote:
>> Dear python-dev,
>>
>> In mathematical notation, f*g = z->f(g(z)) and f^n = f*f*f... (n
>> times). I often run into situations in python where such operators
>> could result in cleaner code. Eventually, I decided to implement it
>> myself and see how it worked in practice.
>>
>> However, my intuitive implementation [1] doesn't seem to work. In
>> particular, despite what it says in function's documentation, function
>> does not seem to be in __builtin__. Furthermore, when I try to
>> implement this through type(f) (where f is a function) I get invalid
>> syntax errors.
>>
>> I hope I haven't made some trivial error; I'm rather inexperienced as
>> a pythonist.
>>
>> Christopher Olah
>>
>>
>> [1] Sketch:
>>
>> def __builtin__.function.__mul__(self, f):
>> return lambda x: self(f(x))
>>
>> def __builtin__.function.__pow__(self, n):
>> return lambda x: reduce(lambda a,b: [f for i in range(n)]+[x])
As Reid explained, you can't just muck around with built-in types like
that. However, you can "use a different type".
If you're not familiar with Python decorators, look them up, and then
have a look at this simple implementation of what you were looking for:
>>> class mfunc:
... def __init__(self, func):
... self.func = func
... self.__doc__ = func.__doc__
... self.__name__ = func.__name__
... def __call__(self, *args, **kwargs):
... return self.func(*args, **kwargs)
... def __mul__(self, f2):
... @mfunc
... def composite(*a, **kwa):
... return self.func(f2(*a, **kwa))
... return composite
... def __pow__(self, n):
... if n < 1:
... raise ValueError(n)
... elif n == 1:
... return self.func
... else:
... return self * (self ** (n-1))
...
>>> @mfunc
... def square(x): return x*x
...
>>> @mfunc
... def twice(x): return 2*x
...
>>> (square*twice)(1.5)
9.0
>>> addthree = mfunc(lambda x: x+3)
>>> addfifteen = (addthree ** 5)
>>> addfifteen(0)
15
>>>
More information about the Python-Dev
mailing list