`functools.pipe`

This concept is for single argument function composition. Not to be confused with iterator piping.

Having that said, composing iterator functions via function composition achieves linear iterator piping.

E.g.:

pipeline = pipe(
    partial(filter, lambda x: x % 2),
    partial(map, lambda x: x/2),
    list
)
pipeline([0, 1, 2, 3, 4])
# [0.5, 1.5]

For more complex iterator piping (multiple argument function composition) there is a FunctionType for that.

For outer (outside of member functions) logging / debugging, one can write a function to mix into a pipeline. E.g.:

def log_debug(x, is_iterator=False):
    if is_iterator:
        for el in x:
            breakpoint()
            print(x)
            yield x
    else:
        breakpoint()
        print(x)
    return x