📜  Python|调用或定义函数时的范围解析

📅  最后修改于: 2022-05-13 01:55:28.637000             🧑  作者: Mango

Python|调用或定义函数时的范围解析

Python通过两种方式解析函数参数的范围:

  • 定义函数时
  • 调用函数时

定义函数时
考虑这个示例程序,它有一个函数adder(a, b),它将元素 a 添加到列表 b 并返回列表 b。 b 的默认值为 [1, 8, 11]。

代码 :

def adder(a, b = [1, 8, 11]):
    b.append(a)
    return b
  
print(adder(1))
print(adder(2))
print(adder(9))
print(adder(2, [3, 6]))
Expected Output : 

[1, 8, 11, 1]
[1, 8, 11, 2]
[1, 8, 11, 9]
[3, 6, 2]
Actual Output : 

[1, 8, 11, 1]
[1, 8, 11, 1, 2]
[1, 8, 11, 1, 2, 9]
[3, 6, 2]

请注意,即使我们在第 2 次和第 3 次调用中没有传递参数,b 的默认值也不再保持为 [1, 8, 11]。这是因为Python仅在定义函数时解析对函数范围内默认参数名称的引用,而不是在每次调用时解析。即使 a 和 b 是任何其他可变类型,如dict 和 set ,程序也会以相同的方式工作。
如果我们希望 b 的默认值始终为 [1, 8, 11] 怎么办?在函数内部,我们可以检查调用函数时是否传递了 b。如果不是,那么我们将 b 的值重新分配给 [1, 8, 11]。调用函数时
现在,考虑这个程序,它试图将 lambda函数对象(计算 0 到 4 之间的数字的平方)存储在一个列表中,并一个一个地调用它们。
代码 :

l = []
for i in range(5):
    l.append(lambda : i**2)
for j in range(5):
    print(l[j]())
Expected Output : 

0
1
4
9
16
Actual Output : 

16
16
16
16
16

然而,结果并不是该程序所期望的。这是因为Python在调用函数时解析对函数范围内非默认参数名称的引用,而不是在定义函数时解析。这里的参数是i 。当循环终止时, i的值为 4,当我们调用存储在 l 中的任何 lambda 函数时,返回 4**2 = 16。
我们怎样做才能使程序按我们预期的方式运行?只需将i设为 lambda函数的默认参数,然后让 python 的作用域解析行为为您执行此操作。