函数相关注意事项

默认参数值的陷阱

默认参数值在函数定义的时候并得到计算,如下:

i = 5

def f(arg=i):
    print(arg)

i = 6
f()

最后输出的结果为5,因为默认值已在函数定义时得到计算。
重要警告:默认值仅被计算一次。 当默认值是可变对象(例如列表,字典或大多数类的实例)时,这会有所不同。 例如,以下函数累积在后续调用中传递给它的参数:

def f(a, L=[]):
    L.append(a)
    return L

print(f(1))
print(f(2))
print(f(3))

这段代码将输出:

[1]
[1, 2]
[1, 2, 3]

这是因为L的默认值在定义时为[],且只会计算一次,当多次调用该函数时,L的默认值不会重新计算为[],而是原先的list对象,又因为list对象为可变类型。
如果不希望在后续调用之间共享默认参数值,则可以编写如下函数:

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L

# 捕获匿名函数中的变量 使用lambda定义匿名函数时,通常想捕获周围的变量作为函数参数 ,或函数体内部变量想捕获lambda外的变量值。示例:
>>> x = 10
>>> a = lambda y: x + y
>>> x = 20
>>> b = lambda y: x + y 
>>>

当调用a(10)和b(10),可能通常觉得会输出20和30。但实际输出的都是30,这里的问题是,lambda表达式中使用的x的值是一个自由变量,它在运行时而不是定义时绑定。 因此,lambda表达式中的x值等于执行时x变量的值
如果希望匿名函数在定义点捕获值并将其保留,则需使用关键字参数获取该值为默认值,如下所示:

>>> x = 10
>>> a = lambda y, x=x: x + y
>>> x = 20
>>> b = lambda y, x=x: x + y 
>>> a(10)
20
>>> b(10)
30
>>>

另外一个例子:

>>> funcs = [lambda x: x+n for n in range(5)] 
>>> for f in funcs:
...     print(f(0))
...
4
4
4
4
4 
>>>

在for循环调用时,n的值为4,故所有的输出都为4。

>>> funcs = [lambda x, n=n: x+n for n in range(5)] 
>>> for f in funcs:
...     print(f(0))
...
0
1
2
3
4 
>>>

n使用关键字参数,则在定义时获取迭代的默认值。

posted @ 2019-11-29 00:07  Jeffrey_Yang  阅读(195)  评论(0编辑  收藏  举报