Применить список функций для объекта в 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']