转载:python默认参数的副作用
Daviesliu在他的blog中提到了python中值得注意的事情,现转载如下
作者:DaviesLiu
地址:http://blog.daviesliu.net/article/entry20061129-103307
注:该问题在Python 2.4 的 Tutorial 4.7.1 已经提出了,感谢 Rogerz 提醒。
看看下面这段程序的运行结果:
def foo(arg={}):
print arg
arg['key'] = "value"
foo()
foo()
其输出结果为:
{}
{'key': 'value'}
同一个函数,两次运行的结果居然不一样,它做了一些我们不期望的事情,称这个函数具有副作用。这段程序中,foo函数中是打印默认参数arg的值,应该为{},而第二次运行时默认值居然便成了{'key':'value'},诡异!
Python
是完全面向对象的动态语言,函数也是一个动态的对象,函数的默认参数为该对象的func_defaults属性,在函数foo中,
func_defaults为({},)。arg的默认值是一个空字典,为可修改对象。当函数没有传递参数时,参数arg指向func_defaults
中这个可修改的字典,后面对arg的操作也就是对func_defaults中该字典的操作,修改arg也就修改了函数对象的属性,于是产生了副作用,与
期望的行为不符。
默认参数的副作用,与传递可修改对象参数时的副作用是一样的。为了避免副作用,默认参数尽量采用不可修改的类型,比如将上面的程序段改成下面的样子将没有副作用:
def foo(arg=None):
if not arg: arg = {}
print arg
arg['key'] = "value"
CommentsRe:Python中默认参数的副作用
ActivePython 2.4的文档Tutorial 4.7.1上有提到这个。参数的默认值只被初始化一次。
由 章鱼 发表于 Wed Nov 29 12:50:28 2006
Re:Python中默认参数的副作用
不过副作用与参数的默认值只初始化一次没有关系,它与Python的对象模型有关,凡是引用可修改对象时都会有副作用。比如
ll = []
def foo(l = ll):
print l
ll.append(1)
foo()
将输出 [1]
由 davies
发表于 Wed Nov 29 16:35:58 2006