我从Python hitchhikers guide发现了这个例子:
def create_multipliers():
return [lambda x, i=i : i * x for i in range(5)]
上面的例子解决了后期绑定引起的一些问题,其中闭包中使用的变量在调用内部函数时被查找。
i = i是什么意思,为什么会产生这样的差异?
答案 0 :(得分:3)
在这种情况下,范围中的每个数字都将分配给每个lambda函数的可选参数:
def create_multipliers():
return [lambda x, i=i : i * x for i in range(5)]
lambda x, i=0
lambda x, i=1
lambda x, i=2
lambda x, i=3
lambda x, i=4
因此,您现在可以使用一个参数调用函数(因为它们已经具有默认值)
for f in create_multipliers():
print(f(3))
0
3
6
9
12
或者您可以调用该函数并提供您想要的参数,这就是为什么是可选的
for f in create_multipliers():
print(f(3,2))
6
6
6
6
6
有些例子需要可选参数,例如递归
例如,方形的平方:
square = lambda n, m=0: 0 if n==m else n+square(n,m+1)
看看那里的可选参数是否用作累加器
答案 1 :(得分:2)
它实际上不只是为了lambdas;任何采用默认参数的函数都将使用相同的语法。例如
def my_range(start, end, increment=1):
ans = []
while start < end:
ans.append(start)
start += increment
return ans
(实际上这不是范围如何工作,我只是认为这是一个简单的例子来理解)。在这种情况下,您可以致电my_range(5,10)
,然后获得[5,6,7,8,9]
。但您也可以拨打my_range(5,10,increment=2)
,这会给您[5, 7, 9]
。
使用默认参数可以获得一些令人惊讶的结果。正如this excellent post所描述的那样,参数绑定在函数定义中,而不是像您期望的那样在函数调用中绑定。这会导致一些奇怪的行为,但它实际上对我们有所帮助。请考虑链接中提供的错误代码:
def create_multipliers():
return [lambda x : i * x for i in range(5)]
for multiplier in create_multipliers():
print multiplier(2)
当你致电multiplier(2)
时,它到底在做什么?它输入您的输入参数2,然后返回i * 2
。但是什么是i
?该函数在其自己的作用域中没有任何名为i
的变量,因此它会检查周围的作用域。在周围的范围内,i
的值就是你留下的任何值 - 在这种情况下为4.所以每个函数都给你8个。
另一方面,如果提供默认参数,则该函数在其自己的范围内有一个名为i
的变量。 i
的价值是什么?好吧,你没有提供一个,所以它使用默认值,该值在定义函数时被绑定。当定义函数时,i
对列表中的每个函数都有不同的值!
他们对参数变量使用与迭代变量相同的名称,这有点令人困惑。我怀疑你可以用
获得更好的可读性def create_multipliers():
return [(lambda x, y=i: y*x) for i in range(5)]