The Mysterious Function List

date
Jan 12, 2022
slug
the-mysterious-lambda-function-list
status
Published
summary
Scope matters.
type
Post
tags
Python
I’m always writing list comprehensions in Python. Once I tried to get a list of lambda functions using a list comprehension, and later I found that the functions are all the same - they were supposed to be different.
The case was very simple:
phi = [lambda x: x**i for i in range(5)]
We would expect the i-th term in this list return a degree-i polynomial of the input, this is pretty intuitive. However, when tested, suprisingly -
>>> phi[0](10) 10000 >>> phi[1](10) 10000 >>> phi[2](10) 10000
They are supposed to return 1, 10 and 100. What happened?
This is actually something covered in the official document since Python 3.4:
Apparently, the i variable here is defined outside the scope of the lambda functions. In another sense, all these lambda functions here are actually the same, but in diffenent addresses. When called, they all search for variable i in their outer scope, and return x**i. This means all of them will be referencing the last i in loop, no matter it’s a list comprehension or a for loop, a lambda function or a proper function.
The solution is also simple - use a default parameter. In this way the i’s will be recorded when initializing the function in its scope, and it will work as we wish.
phi = [lambda x, deg=i: x**deg for i in range(5)] >>> phi[0](10) 1 >>> phi[1](10) 10 >>> phi[2](10) 100
 
If you have any questions, please contact me.