views:

41

answers:

3

Hi,

In python I defined functions:

def foo_1(p): return p + 1
def foo_2(p): return p + 1
def foo_3(p): return p + 1
def foo_4(p): return p + 1
def foo_5(p): return p + 1

I need execute those function as a chain may like this:

foo_1(foo_2(foo_3(foo_4(foo_5(1)))))

May I know if I can push the functions into a list then execute those functions as a chain, also maybe I can give an executing sequence?

lf = [Null,foo_1,foo_2,foo_3,foo_4,foo_5]  # Null is for +1 issue here

def execu(lst, seq, raw_para):
    # in some way

execu(lf,(1,2,3,4,5), 1)   # = foo_1(foo_2(foo_3(foo_4(foo_5(1)))))
execu(lf,(1,2,3), 1)       # = foo_1(foo_2(foo_3(1)))
execu(lf,(3,3,3), 1)       # = foo_3(foo_3(foo_3(1)))

Thanks!

Rgs,

KC

+1  A: 
def execu(lst, seq, raw_para):
  return reduce(lambda x, y: y(x), reversed(operator.itemgetter(*seq)(lst)), raw_para)
Ignacio Vazquez-Abrams
why reversed here?
K. C
`reduce()` handles the elements from beginning to end. Your example shows them being invoked from end to beginning.
Ignacio Vazquez-Abrams
ah, IC, the stack should from end to begin, thanks
K. C
Please don't encourage people to write code like this. @dugres shows the approach which is sane, obvious, and instantly understandable. This is just trying to be clever, to no benefit and resulting in very hard-to-understand code.
Glenn Maynard
+1  A: 

You can use reduce for this:

reduce(lambda x, y: y(x), list_of_functions, initial_value)

Like so:

reduce(lambda x, y: y(x), reversed([foo_1, foo_2, foo_3, ...]), 1)

Note that If you want to apply the functions in the order of foo_1(foo_2(etc...)), you have to make sure that foo_1 is the last element of the list of functions. Therefore I use reversed in the latter example.

Deniz Dogan
Unfortunately this will compose the functions in the wrong order. `...(foo_3(foo_2(foo_1(1))))`
Ignacio Vazquez-Abrams
Good call, Ignacio, I'll add a `reversed` call.
Deniz Dogan
+3  A: 

No need for "Null" in "lf".

def execu(lst, seq, raw_para):  
    para=raw_para  
    for i in reversed(seq):  
        para=lst[i](para)
    return para
dugres
+1, but I think 1st None (Null?) is required, or use `lst[i-1]`
Michał Niklas
`seq` values are indexes into `lst`, so no change is needed here. Rather, if you remove the unnecessary None from the OP's list you also need to shift the indexes down one to match. I'd suggest removing `para` and renaming `raw_para` to `para` to simplify.
Glenn Maynard
This code has got to be the first thing everyone thinks of. I don't know why everyone else felt it was an improvement to bring reduce and lambda into the picture.
Glenn Maynard
#Glenn Maynard, thanks for your idea and programming code style suggestion, dugres's solution is more traditional and natural idea similar as a recursion solution. It is OK and easy to use but I think the python beginner such as me may think the reduce() is much cool. Same as the first time I know the List Comprehensions in python, that's why I accepted the right answer to the reduce, if there's 2 acceptable answers, I will give another on to dugres.
K. C