Применить список функций к объекту в Python
есть ли какой-либо чистый способ применить список функций к объекту в Python без понимания лямбда или списка? Как выражение Хаскелла:
map ($ obj) [foo1,foo2]
пример с лямбдой в Python:
response = map(lambda foo:foo(obj),[foo1,foo2]) #fooX:object->Bool
является ли он расширяемым для функций класса?
возможно, что-то от оператора или itertools?
4 ответов
Я думаю, что это должно соответствовать вашим "функциональным" критериям, чтобы ответить на ваш вопрос, я не думаю, что есть чистый способ, и вы должны просто акклиматизироваться, чтобы перечислить понимания.
как предложено @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]
вы всегда можете просто создать функцию, чтобы заботиться о нем для вас:
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])
проблема отсутствует $
оператор, который тривиально определен
def apply(f, a):
return f(a)
тогда можно сделать карри ($ obj)
С частичным в Python, как это: partial(apply, a=obj)
имея это, мы можем сделать карту применить с
map(partial(apply, a=obj), [foo1, foo2]))
Я думаю, что понимание списка-лучший способ построить один список на основе другого. Применение регулярных функций из списка довольно просто:
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)