python 函数默认参数的小坑

默认参数和可变对象

在执行def语句时,默认参数的值只被解析并保存一次,而不是每次在调用函数的时候。这通常是你想要的那样,但是因为默认值需要在每次调用时都保持同样对象,你在试图改变可变的默认值(mutable defaults)的时候可要小心了。例如,下面的函数中使用一个空的列表作为默认值,然后在之后每一次函数调用的时候改变它的值:

1
2
3
4
5
6
7
8
9
10
11
12
>>> def saver(x=[]):   # 保存一个列表对象
...     x.append(1)    # 并每次调用的时候
...     print x     # 改变它的值
...
>>> saver([2])         # 未使用默认值
[2, 1]
>>> saver()            # 使用默认值
[1]
>>> saver()            # 每次调用都会增加!
[1, 1]
>>> saver()
[1, 1, 1]

有的人将这个视作Python的一个特点——因为可变的默认参数在每次函数调用时保持了它们的状态,它们能提供像C语言中静态本地函数变量的类似的一些功能。但是,当你第一次碰到它时会觉得这很奇怪,并且在Python中有更加简单的办法来在不同的调用之间保存状态(比如说类)。

要摆脱这样的行为,在函数开始的地方用切片或者方法来创建默认参数的副本,或者将默认值的表达式移到函数里面;只要每次函数调用时这些值在函数里,就会每次都得到一个新的对象:

1
2
3
4
5
6
7
8
9
10
11
>>> def saver(x=None):
...     if x is None: x = []   # 没有传入参数?
...     x.append(1)            # 改变新的列表
...     print x
...
>>> saver([2])                 # 没有使用默认值
[2, 1]
>>> saver()                    # 这次不会变了
[1]
>>> saver()
[1]

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。