Python - Create list of functions in for loop

66 Views Asked by At

I am trying to create a list of functions. For example, if I have a function which takes in two arguments f(x,y) I want to create a list of functions f(x) like [f(x,0), f(x,1), f(x,2), f(x,3)].

Here is a contrived example: Given f(x,i) = x ** i. Make a list [f(x,0), f(x,1), f(x,2), f(x,3)] where the functions in the list accept only one argument. So if the list is named 'a', a function can be called as

a[index](x)

Here are my attempts at coding this problem.

n = 4

def func_creator_1(n):
    func_list = list()
    for i in range(n):
        def func(x):
            return x ** i
        func_list.append(func)
    return func_list

f_list_1 = func_creator_1(n)


def func_creator_2(i):
    def func(x):
        return x ** i
    return func

f_list_2 = [func_creator_2(i) for i in range(n)]


def func_creator_3(n):
    def func_outer(i):
        def func(x):
            return x ** i
        return func
    func_list = [func_outer(i) for i in range(n)]
    return func_list

f_list_3 = func_creator_3(n)


def func_creator_4(n):
    def func_x_i(x,i):
        return x ** i
    return [lambda x: func_x_i(x,i) for i in range(n)]

f_list_4 = func_creator_4(n)


def func_creator_5(n):
    return [lambda x: x**i for i in list(range(n))]

f_list_5 = func_creator_5(n)

Next I assign the variable x to 2 and I print the output. n is already assigned to 4 so that it could be used by the list comprehension below method 2.

x = 2

print('function\tmethod 1\tmethod 2\tmethod 3\tmethod 4\tmethod 5')
print('-'*90)

for c, f_tuple in enumerate(zip(f_list_1, f_list_2, f_list_3, f_list_4, f_list_5)):
    f1, f2, f3, f4, f5 = f_tuple

    print('{}^{}:\t\t{}\t\t{}\t\t{}\t\t{}\t\t{}\n'.format(
          x, c, f1(x), f2(x), f3(x), f4(x), f5(x)))

And here is the output:

function    method 1    method 2    method 3    method 4    method 5  
2^0:        8       1       1       8       8

2^1:        8       2       2       8       8  

2^2:        8       4       4       8       8

2^3:        8       8       8       8       8

Except the format looks better on the console...

Anyway, in my opinion method 1 is the most readable and is representative of how I would code this, but it fails. I'm a python beginner, but my guess is that when the function in the list is created the variable 'i' is some kind of pointer and so all of the list functions reference the same memory location which, upon exiting the loop, has a value of 3.

Method 2 succeeds, but I don't like how I have to have a list comprehension after the function. If I changed n, I would have to call both the func_creator_2 AND redo the list comprehension.

Method 3 is just me bundling the method 2 function and list comprehension step into a single function. It works, and only fixes my complaint about method 2, but it is ugly.

Method 4 was another attempt...

And in method 5 I tried to "copy" or make 'i' variable more permanent. I would have loved for this to work, because it is so clean on short, but it also failed.

So, after all of this, I have two questions:
1.) Why do methods 1, 4, and 5 fail?
2.) What is the most pythonic solution?

I apologize if question two is too much of an opinion question.

Thanks!

0

There are 0 best solutions below