Calling functions in every possible combination - python

I have a list of functions. I want to call each possible combination of these functions, where each function is either called once or not at all. It doesn't matter that order they are in.
Example:
functionList = [function1, function2, function3]
I would like to call function1() on its own and also function1() + function2() and also function1() + function2() + function3() and also function2() etc
How would I implement this in python? I thought to use itertools.combinations however it doesn't seem I can use that for my problem.

itertools works fine. But you need to go through the number that you want to use...between 1 and the number in your set. not sure if you need 0 as your degenerate case. The following works. It could be compressed but as-is it's pretty readable. Look up "python function pointer".
import itertools as it
def f1():
return 1
def f2():
return 2
def f3():
return 3
functionList = [f1, f2, f3]
fsets = set([])
for num in range(1, len(functionList)+1):
for combo in it.combinations(functionList, num):
fsets.add(combo)
for fc_combo in fsets:
temp = 0
for f in fc_combo:
temp += f()
print temp

You can use powerset function from the the itertools recipe page:
from itertools import chain, combinations
def powerset(iterable):
"""
powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)
"""
xs = list(iterable)
# note we return an iterator rather than a list
return chain.from_iterable(combinations(xs,n) for n in range(len(xs)+1))
def f1():
return "f1"
def f2():
return "f2"
def f3():
return "f3"
functions = [f1, f2, f3]
for function_comb in powerset(functions):
out = ""
if not function_comb:
continue # skip the empty set of functions
for f in function_comb:
out += f()
print out
It produces the following output:
f1
f2
f3
f1f2
f1f3
f2f3
f1f2f3

Related

Chaining functions calls on some list

Let's say I have three functions and it needs to process a list one after another.
def f1(lst):
lst_processed = do_something_of_type1(lst)
return lst_processed
def f2(lst):
lst_processed = do_something_of_type2(lst)
return lst_processed
def f3(lst):
lst_processed = do_something_of_type3(lst)
return lst_processed
I would like to apply these three functions on some input_list in the following order: f1, then f2 since f2 needs the processed list from f1 and finally f3 which needs the return value of f2.
Option 1:
output_list = f3(f2(f1(input_list)))
Option 2:
output_list1 = f1(input_list)
output_list2 = f2(output_list1)
output_list = f3(output_list2)
Does one of these comply with PEP 8 more so than the other?
From this answer: Is there a chain calling method in Python?
def f1(i):
return i + 1
def f2(i):
return i + 1
def f3(i):
return i + 1
def f4(i):
return i + 1
from functools import reduce
def chain(*funcs):
def chained_call(arg):
return reduce(lambda r, f: f(r), funcs, arg)
return chained_call
chained = chain(f1, f2, f3, f4)
print(chained(0))
I don't think there's actually anything built-in to do this (functools seemed like the most likely place to find something), but it's also relatively easy to write the kind of thing you'd find there
def chainfunc(funcs, arg):
ret = arg
for f in funcs:
ret = f(arg)
return ret
output_list = chainfunc([f1, f2, f3], lst)
That said, you can also coerce functools.reduce() into doing something like this in a one-liner:
from functools import reduce
output_list = reduce(lambda a, b: b(a), [f1, f2, f3], lst)
I would put option 2 in a function of it’s own, and then call that. Also, I wouldn’t call them f1, f2, etc.
option 1 is more pythonic, but depends for whom you are writing your code.
For my opinion option 2 is more readable for junior developers.
Have you searched the pep8 documentation?
Why do you need 3 functions?
def f(lst):
lst_1 = do_something_of_type1(lst)
lst_2 = do_something_of_type2(lst_1)
lst_processed = do_something_of_type3(lst_2)
return lst_processed

Python: How to use for loop to call all the functions?

I want to use the f_i function like this:
for i in range (9):
f_i(y)=c
But I don't know how to use the value of i to call all my ten functions. So what should I do?
Make a list containing the functions and use each function by using loop as follows.
def f1(x):
return x
def f2(x):
return x * 2
def f3(x):
return x * 3
function_list = [f1, f2, f3]
for f in function_list:
print(f(1))
Assume functions is defined/imported into the current file.
locals().get() is the thing that you want
for i in range (9):
func = locals().get("f_{}".format(i))
func(y)

Python: easiest way to flatten a tupple containing another tupple from a function

My code is like this:
def f1():
return 2, 3
def f2():
return 1, f1()
I can do:
a, (b, c) = f2()
I want to do:
a, b, c = f2()
All the solutions I could find require using a lot of insane parenthesis/brackets, or creating an identity function to use * operator. I would like to only modify f2().
Is there something simpler?
Instead of using 1, f2(), use tuple concatenation:
def f2():
return (1,) + f1()
As mentioned in a comment, you could also do this:
def f2():
x,y = f1()
return 1, x, y
You could also do this:
def f2():
return (lambda *args: args)(1, *f1())
That is a little long, but it has an advantage over the x,y = f1() solution because this way f1() can return a tuple with any number of elements.

map with lambda vs map with function - how to pass more than one variable to function?

I wanted to learn about using map in python and a google search brought me to http://www.bogotobogo.com/python/python_fncs_map_filter_reduce.php which I have found helpful.
One of the codes on that page uses a for loop and puts map within that for loop in an interesting way, and the list used within the map function actually takes a list of 2 functions. Here is the code:
def square(x):
return (x**2)
def cube(x):
return (x**3)
funcs = [square, cube]
for r in range(5):
value = map(lambda x: x(r), funcs)
print value
output:
[0, 0]
[1, 1]
[4, 8]
[9, 27]
[16, 64]
So, at this point in that tutorial, I thought "well if you can write that code with a function on the fly (lambda), then it could be written using a standard function using def". So I changed the code to this:
def square(x):
return (x**2)
def cube(x):
return (x**3)
def test(x):
return x(r)
funcs = [square, cube]
for r in range(5):
value = map(test, funcs)
print value
I got the same output as the first piece of code, but it bothered me that variable r was taken from the global namespace and that the code is not tight functional programming. And there is where I got tripped up. Here is my code:
def square(x):
return (x**2)
def cube(x):
return (x**3)
def power(x):
return x(r)
def main():
funcs = [square, cube]
for r in range(5):
value = map(power, funcs)
print value
if __name__ == "__main__":
main()
I have played around with this code, but the issue is with passing into the function def power(x). I have tried numerous ways of trying to pass into this function, but lambda has the ability to automatically assign x variable to each iteration of the list funcs.
Is there a way to do this by using a standard def function, or is it not possible and only lambda can be used? Since I am learning python and this is my first language, I am trying to understand what's going on here.
You could nest the power() function in the main() function:
def main():
def power(x):
return x(r)
funcs = [square, cube]
for r in range(5):
value = map(power, funcs)
print value
so that r is now taken from the surrounding scope again, but is not a global. Instead it is a closure variable instead.
However, using a lambda is just another way to inject r from the surrounding scope here and passing it into the power() function:
def power(r, x):
return x(r)
def main():
funcs = [square, cube]
for r in range(5):
value = map(lambda x: power(r, x), funcs)
print value
Here r is still a non-local, taken from the parent scope!
You could create the lambda with r being a default value for a second argument:
def power(r, x):
return x(r)
def main():
funcs = [square, cube]
for r in range(5):
value = map(lambda x, r=r: power(r, x), funcs)
print value
Now r is passed in as a default value instead, so it was taken as a local. But for the purposes of your map() that doesn't actually make a difference here.
Currying is another option. Because a function of two arguments is the same as a function of one argument that returns another function that takes the remaining argument, you can write it like this:
def square(x):
return (x**2)
def cube(x):
return (x**3)
def power(r):
return lambda(x): x(r) # This is where we construct our curried function
def main():
funcs = [square, cube]
for y in range(5):
value = map(power(y), funcs) # Here, we apply the first function
# to get at the second function (which
# was constructed with the lambda above).
print value
if __name__ == "__main__":
main()
To make the relation a little more explicit, a function of the type (a, b) -> c (a function that takes an argument of type a and an argument of type b and returns a value of type c) is equivalent to a function of type a -> (b -> c).
Extra stuff about the equivalence
If you want to get a little deeper into the math behind this equivalence, you can see this relationship using a bit of algebra. Viewing these types as algebraic data types, we can translate any function a -> b to ba and any pair (a, b) to a * b. Sometimes function types are called "exponentials" and pair types are called "product types" because of this connection. From here, we can see that
c(a * b) = (cb)a
and so,
(a, b) -> c ~= a -> (b -> c)
Why not simply pass the functions as part of the argument to power(), and use itertools.product to create the required (value, func) combinations?
from itertools import product
# ...
def power((value, func)):
return func(value)
for r in range(5):
values = map(power, product([r], funcs))
print values
Or if you don't want / require the results to be grouped by functions, and instead want a flat list, you could simply do:
values = map(power, product(range(5), funcs))
print values
Note: The signature power((value, func)) defines power() to accept a single 2-tuple argument that is automatically unpacked into value and func.
It's equivalent to
def power(arg):
value, func = arg

Creating a new function as return in python function?

I was wondering if it is possible in python to do the following:
def func1(a,b):
return func2(c,d)
What I mean is that suppose I do something with a,b which leads to some coefficients that can define a new function, I want to create this function if the operations with a,b is indeed possible and be able to access this outside of func1.
An example would be a simple fourier series, F(x), of a given function f:
def fourier_series(f,N):
...... math here......
return F(x)
What I mean by this is I want to creat and store this new function for later use, maybe I want to derivate it, or integrate or plot or whatever I want to do, I do not want to send the point(s) x for evaluation in fourier_series (or func1(..)), I simply say that fourier_series creates a new function that takes a variable x, this function can be called later outside like y = F(3)... if I made myself clear enough?
You should be able to do this by defining a new function inline:
def fourier_series(f, N):
def F(x):
...
return F
You are not limited to the arguments you pass in to fourier_series:
def f(a):
def F(b):
return b + 5
return F
>>> fun = f(10)
>>> fun(3)
8
You could use a lambda (although I like the other solutions a bit more, I think :) ):
>>> def func2(c, d):
... return c, d
...
>>> def func1(a, b):
... c = a + 1
... d = b + 2
... return lambda: func2(c,d)
...
>>> result = func1(1, 2)
>>> print result
<function <lambda> at 0x7f3b80a3d848>
>>> print result()
(2, 4)
>>>
While I cannot give you an answer specific to what you plan to do. (Looks like math out of my league.)
I can tell you that Python does support first-class functions.
Python may return functions from functions, store functions in collections such as lists and generally treat them as you would any variable.
Cool things such as defining functions in other functions and returning functions are all possible.
>>> def func():
... def func2(x,y):
... return x*y
... return func2
>>> x = func()
>>> x(1,2)
2
Functions can be assigned to variables and stored in lists, they can be used as arguments for other functions and are as flexible as any other object.
If you define a function inside your outer function, you can use the parameters passed to the outer function in the definition of the inner function and return that inner function as the result of the outer function.
def outer_function(*args, **kwargs):
def some_function_based_on_args_and_kwargs(new_func_param, new_func_other_param):
# do stuff here
pass
return some_function_based_on_args_and_kwargs
I think what you want to do is:
def fourier_series(f,N):
#...... math here......
def F(x):
#... more math here ...
import math #blahblah, pseudo code
return math.pi #whatever you want to return from F
if f+N == 2: #pseudo, replace with condition where f,N turn out to be useful
return F
else:
return None
Outside, you can call this like:
F = fourier_series(a,b)
if F:
ans = F(x)
else:
print 'Fourier is not possible :('
The important thing from Python's point of view are:
Yes, you can write a function inside a function
Yes, you can return a function from a function. Just make sure to return it using return F (which returns the function object) as compared to return F(x) which calls the function and returns the value
I was scraping through some documentation and found this.
This is a Snippet Like your code:
def constant(a,b):
def pair(f):
return f(a,b)
return pair
a = constant(1,2) #If You Print variable-> a then it will display "<function constant.
#<locals>.pair at 0x02EC94B0>"
pair(lambda a, b: a) #This will return variable a.
Now, constant() function takes in both a and b and return a function called "Anonymous Function" which itself takes in f, and calls f with a and b.
This is called "closures". Closures is basically an Instance of a Function.
You can define functions inside functions and return these (I think these are technically closures):
def make_f(a, b):
def x(a, b):
return a+b
return x(a, b)

Categories