Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use an operator to compose functions?

It's fairly straightforward to write a function that composes two other functions. (For simplicity, assume they are one parameter each.)

def compose(f, g):
    fg = lambda x: f(g(x))
    return fg

def add1(x):
    return x + 1

def add2(x):
    return x + 2

print(compose(add1, add2)(5))  # => 8

I would like to do composition using an operator, e.g., (add1 . add2)(5).

Is there a way to do that?

I tried various decorator formulations, but I couldn't get any of them to work.

def composable(f):
  """
    Nothing I tried worked. I won't clutter up the question 
    with my failed attempts.
  """

@composable
def add1(x):
    return x + 1
like image 990
RussAbbott Avatar asked Jan 01 '23 10:01

RussAbbott


1 Answers

First only a certain amount of operator symbols are allowed in Python syntax. Dot "." is not a valid operator.

This page (the page is actually about the Python operator module, but the naming convention are the same to datamodel and the content is more organized) listed all available operators and the corresponding instance methods. For example, if you want to use "@" as the operator, you can write a decorator like this:

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)

To test:

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

@Composable
def add2(x):
    return x + 2

print((add1 @ add2)(5))
# 8
like image 196
Philip Tzou Avatar answered Feb 08 '23 03:02

Philip Tzou