Python - applying tupple to a function in functional toolz.pipe

425 Views Asked by At

I want to use a function which accepts some arguments in a toolz.pipe, but data input is a tuple. I know how to solve it, but I think there must be some solution in builtin python libraries or in toolz, I just wasnt able to find it.

Example:

def my_func(a, b):
    return a + b

result = pipe(
    (10, 20),
    my_func,
    ...,
)

For those unfamiliar with toolz, pipe is something like:

def pipe(val, *functions):
    data = val
    for fn in functions:
        data = fn(data)
    return data

What I tried:

I know how to solve it, for example this way:

result = pipe(
    (10, 20),
    lambda x: my_func(*x),
    ...,
)

But I find this ugly and I'd like to be able to use some sort of apply function which encapsulates that lambda. I defined mine apply_ like this:

from toolz import pipe

def my_func(a, b):
    return a + b

def apply_(func):
    return lambda x: func(*x)

result = pipe(
    (10, 20),
    apply_(my_func),
)
print(result)

But this seems like something so basic, I'm almost convinced it must exist in builtin python libraries or in toolz package..

Question:

Is there some form of apply wrapper like I described above (apply_), which I have overlooked?

4

There are 4 best solutions below

5
Drey On

For example:

import toolz
import itertools

def my_func(a, b):
    return a + b


list(toolz.pipe(
    [(10, 20), (30, 40)],
    toolz.curry(itertools.starmap)(my_func)
))

The output:

[30, 70]

Edit I was wrong with my intial solution, but I think itertools's starmap is the way to go.

1
Paulo Sergio Schlogl On

toolz have the c.map that you can use:

import toolz as tz
from toolz import curried as c

tz.pipe(data, c.map(function), ...)
1
MonkChen On

Two years late but I think what you're looking for is reduce:

from toolz import pipe, partial, reduce
    
def my_func(a, b):
    return a + b

result = pipe(
    (10, 20),
    partial(reduce, my_func),
)
print(result)
0
Al Aric On

Seems like starmap as suggested elsewhere is a great approach, but you don't want to iterate over the elements of your tuple, you want the tuple to be the (only) element of an iterable:

from itertools import starmap
from operator import methodcaller as dot
from toolz.curried import partial, partition, pipe

def my_func(a, b, c):
    return f"a:{a}, b:{b}, c:{c}"

pipe(
    (1,2,3),
    partition(3),  # length of the tuple
    partial(starmap, my_func),
    dot("__next__"),
)

gives

'a:1, b:2, c:3'