1

I recently implemented a function factory that didn't scope a variable the way I expected.

I found a solution, but I don't know why it works.

So although I don't strictly need a solution to this problem, I've posted this question in the hope of learning something about variable scope.

Problematic Code

# Create function list
func_list = []
for i in [1, 2]:
    def _func():
        print("%i" % i)
    func_list.append(_func)

# Execute
for f in func_list:
    f()

Gives the same ouptut; always the last loop element:

2
2

Solution

# Create function list
def make_func(i):
    def _func():
        print("%i" % i)

    return _func

func_list = []
for i in [1, 2]:
    func_list.append(make_func(i))

# Execute
for f in func_list:
    f()

Gives what I expected all along:

1
2

Why? so my questions are:

  • Why doesn't the first method work?
  • How is the working implementation functionally different to the first?
FraggaMuffin
  • 3,915
  • 3
  • 22
  • 26
  • I guess return function returns the value of it rather than the reference. Hence the second code works out. Though I am not entirely sure. – kawadhiya21 Feb 13 '18 at 10:53

1 Answers1

0

Your solution is called a "closure".

In the first example, i is changed, and the created function returns it. The function doesn't record the value and return it when called. It just returns the current value of i, which has already changed.

In the second example, you define a new i every time you call the outer function and its value is never changed.

kmaork
  • 5,722
  • 2
  • 23
  • 40