Can't extend function type

Christopher Subich csubich.spam.block at spam.subich.block.com
Fri Oct 7 08:59:30 EDT 2005


Diez B. Roggisch wrote:
> Paul Rubin wrote:
> 
>> Oh well.  I had wanted to be able to define two functions f and g, and
>> have f*g be the composition of f and g.
>>
>>     >>> func_type = type(lambda: None)
>>     >>> class composable_function(func_type):
>>     ...   def __mult__(f,g):
>>     ...     def c(*args, **kw):
>>     ...       return f(g(*args, **kw))
>>     ...     return c
>>     ...
>>     Traceback (most recent call last):
>>       File "<stdin>", line 1, in ?
>>     TypeError: Error when calling the metaclass bases
>>         type 'function' is not an acceptable base type
>>     >>>
>>
>> Seems like a wart to me.
> 
> So the only way to achieve this with current semantics is to make f anf 
> g objects with a call methods. In that very moment, you're done - as 
> extending from object is no problem :)
> 
> 
> class ComposeableFunction(object):
> 
>     def __call__(self, *args, **kwargs):
>     return self.second(self.first(*args, **kwargs))

Note, with a little bit of massaging, you can turn ComposableFunction 
into a decorator, for more natural function definition:

(Untested, I'm not on a system with Py2.4 at the moment):
class Composable(object):
     def __init__(self,f):
         self.callable = f
     def __call__(self,*args, **kwargs):
         return self.callable(*args, **kwargs)
     def __mul__(self,other):
         return Composable(lambda (*a, **kwa): self.callable(other(*a, 
**kwa)))

Usage:

@Composable
def f(x):
     return x**2

@Composable
def g(x):
     return x+1

# And we shouldn't even need a @Composable on the last in the sequence
def h(x):
     return x/2.0

 >>>f(1)
1
 >>>(f*g)(1)
4
 >>>(f*g*h)(2)
4

This might not combine neatly with methods, however; the bound/unbound 
method magic is still mostly voodoo to me.



More information about the Python-list mailing list