1

In this question I asked about function composition. @Philip Tzou offered the following code, which does the job.

import functools

class Composable:
    def __init__(self, func):
        self.func = func
        functools.update_wrapper(self, func)

    def __matmul__(self, other):
        return lambda *args, **kw: self.func(other.func(*args, **kw))

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

I attempted to turn this into a function:

from functools import wraps

def composable(func):

    @wraps(func)
    def wrapper(*args, **kw):
        return func(*args, **kw)

    def __matmul__(other):
        return lambda *args, **kw: func(other(*args, **kw))

    wrapper.__matmul__ = __matmul__
    return wrapper

When I run it I get this result.

print((add1.__matmul__(add2))(5)) 
# => 8

So __matmul__ does its job. But,

print((add1 @ add2)(5)) 
# => TypeError: unsupported operand type(s) for @: 'function' and 'function'

The system doesn't recognize that @ can handle two functions.

Why didn't this happen with the class decorator? And, is there a fix for it?

Thanks.

RussAbbott
  • 2,660
  • 4
  • 24
  • 37
  • I don't see how the linked question answers the question I asked. The error message didn't say that there was no function associated with `@`, which is what I would expect if it couldn't find `__matmul__`. It complained about the types of the arguments to `@`. I don't understand where that complaint would be generated. – RussAbbott Jan 13 '19 at 05:58

0 Answers0