Python函数使用可变默认参数出现意外行为的原因及修正方法
Python函数使用可变默认参数出现意外行为的原因及修正方法
嘿,我太懂你这种困惑了!刚接触Python函数默认参数的时候,我也踩过这个一模一样的坑,当时盯着结果愣了好久才搞明白咋回事。
先给你拆解为啥会出现这种情况:
- Python里的函数默认参数,是在函数被定义的那一刻就创建好了,而不是每次调用函数时重新生成。你写的
my_list=[],这个空列表对象在你定义add_to_list函数的时候就已经存在内存里了。 - 之后每次调用函数,如果没有传入
my_list参数,Python都会直接复用这个已经存在的列表对象,而不是新建一个空列表。所以第一次调用add_to_list(1)往这个列表里加了1,第二次调用add_to_list(2)还是往同一个列表里加元素,结果自然就变成[1, 2]了。
你甚至可以做个小测试验证一下,在函数里加一行打印列表的内存地址:
def add_to_list(value, my_list=[]): print(id(my_list)) # 打印对象的内存id my_list.append(value) return my_list print(add_to_list(1)) print(add_to_list(2))
两次打印的id会完全一样,这就实锤了是同一个列表对象在被反复使用。
那怎么改才能达到你想要的效果呢?很简单,把默认参数改成不可变的None,然后在函数内部判断,如果没有传入自定义列表,就新建一个空列表:
def add_to_list(value, my_list=None): # 如果没传my_list,就创建一个全新的空列表 if my_list is None: my_list = [] my_list.append(value) return my_list
这样每次调用函数时,如果不传入my_list,函数内部都会新建一个空列表,自然就不会和之前调用的列表产生关联了。你再测试一下,第一次返回[1],第二次返回[2],完全符合你的预期。
最后再提个醒:不止列表,所有可变对象(比如字典、集合)作为函数默认参数时,都会出现这个问题。因为它们的可变性允许我们修改对象内容,而定义时创建的对象会被持续复用。所以以后写默认参数时,可变对象尽量别直接当默认值,用None来中转是最稳妥的做法。
备注:内容来源于stack exchange,提问作者Mandeep Kumar Roshan
相关产品推荐
相关产品推荐

