python中函数参数的默认值和List, dict

Python 的函数定义中,有种带有默认值的参数的语法,例如:

def foo( p = [] ): 
    print p

如果我们调用此函数的时候,没有传入参数 p ,那 p 就用默认值。

接下来,我们看看下面这段代码会得到什么结果:

def foo( p = [] ):
    p.append('a')
    print p

foo()
foo()

最开始,直觉告诉我,会得到结果:

['a']
['a']

但是实际结果是:

['a']
['a','a']

原来对于这种形式定义的带默认值的参数,参数的默认值是在函数定义的时候初始化的,当我们使用了 mutable 的对象的时候,我们中途改变了这个对象,在后面的函数调用中,它就不再是写在代码里的那个默认值。显然这样是很混乱的,我们不应该这样做。
python 官方文档也解释了这个事情,并且给出了解决方案,当我们需要一个 mutable 的对象作为默认值的时候,我们可以这样做:

def foo( p = None ):
    if p is None:
        p = []
    p.append('a')
    print p

这样每次都是生成一个新的,就没问题了。为了证实,带默认值的参数确实是在函数定义的时候初始化的,我们可以使用 id(p) 这个函数来查看这个变量的 identity , 可以看到,如果不传参数,让函数使用默认值,每次的 id 都是一样的。