其实也不能说是陷阱,只是一个不容易注意到的地方,尤其是有其他java/c++类编程语言经验的人员,这里涉及到python的一个特点,所以笔者说是陷阱只是一个噱头而已。
def test(item, buf = []):
buf.append(buf)
print buf
非常简单的一个函数,功能非常简单,现在看下面的调用代码
test('younger')
test('shen')
输出:
['younger']
['younger', 'shen']
该函数初衷是希望当没有提供默认的buff参数的时候,建立一个空的列表,然后把一个对象添加到该列表中,并且打印, 但是程序的执行似乎并没有按照我们的意图来执行,似乎每个函数都共享了buff,但是我们明明每次都在参数列表中初始化了buff变量,分析如下:
python中的def语句在每次执行的时候都初始化一个函数对象,这个函数对象就是我们要调用的函数,可以把它当成一个一般的对象,只不过这个对象拥有一个可执行的方法和部分属性,对于参数中提供了初始值的参数,由于python中的函数参数传递的是对象,也可以认为是传地址,只有def的时候初始化一次,然后在调用者和被调用者中都是共享的,所以在 func.func_defaults中只能看到一个默认参数,在该函数对象被初始化的时候就已经存在了。
解决这个问题可以用这个方法
def test(item, buf = None):
if buf is None:
buf = []
buf.append(item)
print buf
这样在不给定buf参数的时候可以初始化一次buf,每次都是新的,所以不会出现上面的陷阱,其实这里的None只是占位符而已,用空[]也可以,只不过要需要这样写
def test(item, buf = []):
if len(buf) < 1:
buf = []
buf.append(item)
print buf
这样也可以解决问题,只是看起开不太好而已。
近期除了使用django进行web开发之外,打算重新开始学习linux和操作系统的东西,近期会制定学习计划开始执行。