Python易错知识点之默认参数的使用

一、问题描述:

例如,定义一个函数,传入一个list,添加一个end再返回:

def add_end(l=[]):
    l.append('end')
    return l

1、不使用默认参数调用时,

print add_end([1, 2])

运行结果如下:

[1, 2, 'end']

没有问题。

2、使用默认参数时,

print add_end()
print add_end()

运行结果如下:

['end']
['end', 'end']

可见,第一次调用时返回结果正确,第二次调用时返回结果错误。

二、错因分析:

首先明确,默认参数也是一个变量,python函数在定义的时候,默认参数l的值就被计算出来了,它存储一个空列表[ ]的内存地址(注:python使用引用语义,即python变量保存的是值的引用,采用这种方式,变量所需的存储空间大小一致,因为变量只是保存了一个引用),即它指向空列表[ ],默认参数l存储的这个内存地址不会在该函数被调用的时候再被计算。

调用该函数时若使用默认参数,会对默认参数进行修改,而实际修改的是默认参数指向的列表,默认参数L中存储的仍然是该列表的内存地址。第一次使用默认参数后默认参数指向的列表已经不再为空。

简而言之,就是默认参数的值在定义的时候被计算,调用的时候不会再次被计算。所以每一次函数调用对默认参数的修改都会影响下一次函数调用。

三、解决办法

使默认参数指向不变对象。例如:

def add_end2(l=None):
    if l is None:
        l = []

    l.append('end')
    return l

使用默认参数:

print add_end()
print add_end()

运行结果如下:

['end']
['end']

python不变对象是指该对象在内存中的值不能被改变。当改变某个变量的值时,由于该变量指向的值为不可变对象,会在内存中重新开辟一个新的地址,存储新的值,然后将变量指向这个新的值。原来的内存中的值并不会发生变化。python不变类型包括数值类型(int和float)、字符串(string)、元组(tuple)、None。

python可变对象即该对象在内存中的值可以被改变。变量改变后,实际其所指向的值直接发生改变。python可变类型包括列表(list)、字典(dict)、集合(set)。

设计不可变对象的好处:
1、不变对象一旦创建,其内部的数据就不能修改,这样就减少了由于修改数据导致的错误。
2、由于对象不变,在多任务环境下同时读取不变对象不需要加锁。若对象可变,在多任务环境下读取对象时必须加锁,以防止在读取过程中其它任务对变量进行修改。

牢记:使默认参数指向不变对象。

参考:

https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001374738449338c8a122a7f2e047899fc162f4a7205ea3000

猜你喜欢

转载自blog.csdn.net/weixin_33913332/article/details/87111070