不要用可变类型对象做函数默认参数

1. 可变对象做默认参数

内置数据类型int,float,bool,str,tuple 是不可变对象, 字典,集合,列表是可变对象。

在定义python函数时,千万不要使用可变类型对象作为函数的默认参数,那样会引发意想不到的错误,下面的代码向你展示这种错误

def add_int(value, data=[]):
    data.append(value)
    return data

result = add_int(3)
print(result)  # [3]

我定义了一个add_int函数,默认参数data是一个列表,程序执行结果是[3], 看起来没有什么问题,但是在第2次执行add_int函数时,就会出现意想不到的情况

def add_int(value, data=[]):
    data.append(value)
    return data

result = add_int(3)
print(result)

result = add_int(4)
print(result)

程序输出结果是

[3]
[3, 4]

第2次输出的结果并不是预期的[4], 而是包含了第一次调用函数add_int函数时传入的参数3,这究竟是怎么一回事呢?

2. 函数默认参数

在定义函数时,默认参数只会被计算一次,而不是每次调用函数的时候才计算。python脚本在执行过程中,遇到函数定义的代码,会进行编译,创建一个代码对象,完成编译后,python会将默认参数存储在函数对象之中,准确的说是存储在__defaults__属性中,此后每次调用函数所使用的默认参数都是最开始计算的那一个,而由于这个默认参数是可变对象,所以会导致上面所描述的诡异问题。

def add_int(value, data=[]):
    data.append(value)
    return data

print(add_int.__defaults__)

通过输出__defaults__, 我们可以参看函数的默认参数,程序输出结果是一个元组([],) , 刚刚定义完的函数里,默认参数data还是一个空列表,执行过一次以后,就发生变化了

def add_int(value, data=[]):
    data.append(value)
    return data

print(add_int.__defaults__)

add_int(3)
print(add_int.__defaults__)

程序输出结果

([],)
([3],)

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案