Apply list of functions on an object in Python

Viewed 14535

Is there any clean way to apply a list of functions on an object in Python without lambda or list comprehensions? Like the Haskell expression:

map ($ obj) [foo1,foo2]

Example with lambda in Python:

response = map(lambda foo:foo(obj),[foo1,foo2]) #fooX:object->Bool

Is it extendable to class functions?

Perhaps something from operator or itertools?

7 Answers

The library toolz has a compose function that does just that.

from toolz import compose
compose(foo1, foo2)(obj)

This is my solution:

def plus(i):
    return i+i

def mult(i):
    return i*4

functions = [plus,mult]

result=[]

for i in ["a","b","c","d"]:
    for j in functions:
        result.append(j(i))

result Out[16]: ['aa', 'aaaa', 'bb', 'bbbb', 'cc', 'cccc', 'dd', 'dddd']

I think the question can be read in two ways, apply a list of functions to an object and yield the result of each in a list (Single input, multiple output) OR apply a list of function to an object in sequence (Singe input, single output).

The latter is solved by the compose function, or by defining your own:

def compz(t, funcs):
  return t if not funcs else compz(funcs[0](t), funcs[1:])

print(compz("str", [lambda x: x+"A", lambda x: x+"B", lambda x: x+"C"]))
print(compz("Hello, World", [lambda x: f"<h1>{x}</h1>", lambda x: f"<body>{x}</body>", lambda x: f"<html>{x}</html>",]))
print(compz(2, [lambda x: x+2, lambda x: x+5, lambda x: x+7]))
print(compz(2, [lambda x: x**2, lambda x: x**2, lambda x: x**2]))
print(compz(2, [lambda x: x**2, lambda x: x**2]))
print(compz(2, [lambda x: x**2]))
print(compz(2, []))

strABC
<html><body><h1>Hello, World</h1></body></html>
16
256
16
4
2

Most answers to the latter are equivalent, but really the list comprehension either because the functions are applied in "parallel" not in sequence or because you have to import a separate library. looking at a few answer, it can depend on what your result should look like, i.e. are you okay to have

func_list = [lambda x: x+"A", lambda x: x+"B", lambda x: x+"C"]

print([f("str") for f in func_list])
print([f for f in map(lambda f: f("str"), func_list)])

from functools import partial

def apply(f, a):
    return f(a)
  
print([f for f in map(partial(apply, a="str"), func_list)])

def map_funcs(obj, func_list):
    return [func(obj) for func in func_list]

print(map_funcs("str", func_list))

In all those cases the result is:

['strA', 'strB', 'strC']
Related