Can't extend function type

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Paul Rubin

    #1

    Can't extend function type

    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.
    [color=blue][color=green][color=darkred]
    >>> func_type = type(lambda: None)
    >>> class composable_func tion(func_type) :[/color][/color][/color]
    ... 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[color=blue][color=green][color=darkred]
    >>>[/color][/color][/color]

    Seems like a wart to me.
  • Diez B. Roggisch

    #2
    Re: Can't extend function type

    Paul Rubin wrote:[color=blue]
    > 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.
    >[color=green][color=darkred]
    > >>> func_type = type(lambda: None)
    > >>> class composable_func tion(func_type) :[/color][/color]
    > ... 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[color=green][color=darkred]
    > >>>[/color][/color]
    >
    > Seems like a wart to me.[/color]

    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_fu nction)(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 ComposeableFunc tion(object):

    def __call__(self, *args, **kwargs):
    return self.second(sel f.first(*args, **kwargs))

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


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


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


    f = f()
    g = g()

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


    Diez

    Comment

    • Christopher Subich

      #3
      Re: Can't extend function type

      Diez B. Roggisch wrote:[color=blue]
      > Paul Rubin wrote:
      >[color=green]
      >> 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.
      >>[color=darkred]
      >> >>> func_type = type(lambda: None)
      >> >>> class composable_func tion(func_type) :[/color]
      >> ... 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[color=darkred]
      >> >>>[/color]
      >>
      >> Seems like a wart to me.[/color]
      >
      > 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 ComposeableFunc tion(object):
      >
      > def __call__(self, *args, **kwargs):
      > return self.second(sel f.first(*args, **kwargs))[/color]

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

      (Untested, I'm not on a system with Py2.4 at the moment):
      class Composable(obje ct):
      def __init__(self,f ):
      self.callable = f
      def __call__(self,* args, **kwargs):
      return self.callable(* args, **kwargs)
      def __mul__(self,ot her):
      return Composable(lamb da (*a, **kwa): self.callable(o ther(*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
      [color=blue][color=green][color=darkred]
      >>>f(1)[/color][/color][/color]
      1[color=blue][color=green][color=darkred]
      >>>(f*g)(1)[/color][/color][/color]
      4[color=blue][color=green][color=darkred]
      >>>(f*g*h)(2)[/color][/color][/color]
      4

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

      Comment

      • Paul Rubin

        #4
        Re: Can't extend function type

        "Diez B. Roggisch" <deets@nospam.w eb.de> writes:[color=blue]
        > Well - function inheritance is not known so far in python - and in no
        > other language I know.[/color]

        Yeah, I didn't really expect it to work, but it seems like a logical
        consequence of type/class unification.
        [color=blue]
        > 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?[/color]

        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).
        [color=blue]
        > 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 :)[/color]

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

        Comment

        • Michele Simionato

          #5
          Re: Can't extend function type

          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

          Comment

          • Paul Rubin

            #6
            Re: Can't extend function type

            "Michele Simionato" <michele.simion ato@gmail.com> writes:[color=blue]
            > 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.[/color]

            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.

            Comment

            Working...