class Composition: def __init__(self, f, g=None, repr=None): self.f = f self.g = g def __call__(self, *args, **kwargs): if self.g is None: return self.f(*args, **kwargs) return self.f(self.g(*args, **kwargs)) @property def __name__(self): if self.g is None: return self.f.__name__ return f'{self.f.__name__} >> {self.g.__name__}' def __repr__(self): return self.__name__ class ComposeMeta(type): def __rshift__(self, other): return(self(other)) class Compose(metaclass=ComposeMeta): def __init__(self, func): self._func = Composition(func) def __rshift__(self, other): return self.__class__(Composition(other, self._func)) def __call__(self, *args, **kwargs): return self._func(*args, **kwargs) def __or__(self, other): return self._func(other) def __repr__(self): return repr(self._func)