Can't extend function type

P

Paul Rubin

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.
... 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.
 
D

Diez B. Roggisch

Paul said:
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.

... 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.

Well - function inheritance is not known so far in python - and in no
other language I know.

How do you expect to create f and g, even if above construct would work?
Basdically you want __mult__ being part of f or g when python encounters
something like this

f * g

But then how did you plan to declare f?

def f(composable_function)(x):
pass


obviously won't work.

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))

def __mul__(self, other):
nc = ComposeableFunction()
nc.first = other
nc.second = self
return nc


class f(ComposeableFunction):
def __call__(self, x):
return x * 2


class g(ComposeableFunction):
def __call__(self, x):
return x + 2


f = f()
g = g()

print f(4)
print g(4)
print (f*g)(4)


Diez
 
C

Christopher Subich

Diez said:
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
4

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

Paul Rubin

Diez B. Roggisch said:
Well - function inheritance is not known so far in python - and in no
other language I know.

Yeah, I didn't really expect it to work, but it seems like a logical
consequence of type/class unification.
Basically you want __mult__ being part of f or g when python
encounters something like this

f * g

But then how did you plan to declare f?

Come to think of it, that's also a wart. I'd been thinking of
using a decorator, as Christopher Subich suggested,

@composable
def f(x): ...

but it's not how the decorator could actually work (other than through
gross CPython-specific hacks).
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 :)

Yeah, I thought of that, but felt it wasn't in the proper spirit :)
 
M

Michele Simionato

If you google a bit on the newsgroup, you should find a message
from me asking about the ability to subclass FunctionType, and
a reply from Tim Peters saying that the only reason why this
was not done is lack of developer time and the fact that this was
not considered an important priority.


Michele Simionato
 
P

Paul Rubin

Michele Simionato said:
If you google a bit on the newsgroup, you should find a message
from me asking about the ability to subclass FunctionType, and
a reply from Tim Peters saying that the only reason why this
was not done is lack of developer time and the fact that this was
not considered an important priority.

Yeah, I just thought of it as a perverse but sort of cute way to
implement composition and similar operations on functions. It could
be handy though, and simple to implement, if functions supported the
'*' operator for composition. The example with a callable class is
a possible workaround, but ugly.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,705
Latest member
Stefkari24

Latest Threads

Top