Применить список функций для объекта в Python

Есть ли какой-либо чистый способ применения списка функций на объекте в Python без учета лямбда или списка? Как выражение Haskell:

map ($ obj) [foo1,foo2]

Пример с lambda в Python:

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

Расширяется ли его до функций класса?

Возможно, что-то от оператора или itertools?

Ответ 1

Я думаю, что это должно соответствовать вашим "функциональным" критериям. Чтобы ответить на ваш вопрос, я не думаю, что есть чистый путь, и вы должны просто акклиматизироваться, чтобы перечислить понимание.

Как предложено @J.F.Sebastian

>>> from operator import methodcaller
>>> funcs = (lambda x: x + 1, lambda x: x + 2)
>>> obj = 5
>>> map(methodcaller('__call__', obj), funcs)
[6, 7]

Вот сумасшедший способ сделать это:

>>> from itertools import starmap, repeat
>>> from types import FunctionType
>>> funcs = (lambda x: x + 1, lambda x: x + 2)
>>> obj = 5
>>> list(starmap(FunctionType.__call__, zip(funcs, repeat(obj))))
[6, 7]

Как было предложено @AleksiTorhamo

>>> from itertools import repeat
>>> from types import FunctionType
>>> obj = 5
>>> funcs = (lambda x: x + 1, lambda x: x + 2)
>>> map(FunctionType.__call__, funcs, repeat(obj))
[6, 7]

Ответ 2

Вы всегда можете просто создать функцию, чтобы заботиться о ней для вас:

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

    # I was under the impression that the OP wanted to compose the functions,
    # i.e. f3(f2(f1(f0(obj))), for which the line below is applicable:
    # return reduce(lambda o, func: func(o), func_list, obj)


map_funcs(it, [Buy, Use, Break, Fix])

Ответ 3

Проблема заключается в отсутствии оператора $, который тривиально определяется

def apply(f, a):
    return f(a)

то можно сделать currying ($ obj) с частичным в python следующим образом: partial(apply, a=obj)

имея это, мы можем сделать карту с помощью

map(partial(apply, a=obj), [foo1, foo2]))

Ответ 4

Я думаю, что понимание списков - лучший способ создать один список на основе другого. Применение обычных функций из списка довольно просто:

results = [f(obj) for f in funcList]

Если вам не нужен весь список результатов за один раз, но нужно только перебирать элементы по одному за раз, выражение генератора может быть лучше:

genexp = (f(obj) for f in funcList)
for r in genexp:
    doSomething(r)

Если ваши функции - это методы, а не основные функции, есть два пути:

Использование связанных методов, и в этом случае вам не нужно предоставлять объект вообще при выполнении вызовов функций:

obj = SomeClass()
funcList = [obj.foo1, obj.foo2]
results = [f() for f in funcList]

Или используя несвязанные методы, которые являются просто регулярными функциями, которые ожидают экземпляр класса, в котором они определены как их первый аргумент (условно названный self):

funcList = [SomeClass.foo1, SomeClass.foo2]
obj = SomeClass()
results = [f(obj) for f in funcList]

Конечно, если вам не нужно фиксировать результаты функции, проще всего написать цикл:

for f in funcList:
    f(obj)

Ответ 5

Это мое решение:

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))

результат Out [16]: ['aa', 'aaaa', 'bb', 'bbbb', 'cc', 'cccc', 'dd', 'dddd']