Python函数内删除默认参数后仍复用同一列表的技术疑问
Python 默认参数的可变对象陷阱:为什么
del l 没用? 这个问题其实戳中了Python默认参数的经典坑点,咱们一步步拆解清楚:
首先你说的完全没错——默认参数l=[]确实只在函数定义的时候求值一次。当你写下def f(l=[]):这行代码时,Python就创建了一个空列表对象,并且把它绑定为函数f的默认参数,这个对象会一直存在,除非函数本身被销毁。
那del l到底做了什么?
- 每次调用
f()时,如果没传参数,Python会把那个预先创建的列表赋值给局部变量l。 l.append(1)是直接修改了这个列表对象本身(因为列表是可变对象,操作会改变其内部状态)。- 而
del l只是删除了局部变量l对这个列表对象的引用,并没有删除列表对象本身。这个列表还好好地存在着,因为函数f的默认参数(存在f.__defaults__属性里)还在引用它。
你可以用下面的代码直观验证这个过程:
def f(l=[]): l.append(1) print(l) del l # 查看函数默认参数的初始状态 print(f.__defaults__) # 输出: ([],) f() # 输出: [1] # 再次查看默认参数,已经被修改了 print(f.__defaults__) # 输出: ([1],) f() # 输出: [1, 1] print(f.__defaults__) # 输出: ([1, 1],)
怎么解决这个问题?
如果你希望每次调用函数时都使用一个全新的空列表,正确的写法是把默认参数设为None,然后在函数内部初始化:
def f(l=None): if l is None: l = [] l.append(1) print(l) f() # 输出: [1] f() # 输出: [1]
这样每次调用时,只要没传参数,就会在函数内部创建一个新的空列表,不会再复用之前的对象了。
内容的提问来源于stack exchange,提问作者Ronan Soares
相关产品推荐
相关产品推荐

