Python类方法列表参数继承上一次执行状态的问题排查
解决Python中默认可变参数导致的Graph遍历bug
这是个非常典型的Python默认参数陷阱,我刚学Python的时候也踩过一模一样的坑!
问题根源
Python里函数的默认参数是在函数定义时就初始化好的,而不是每次调用函数时重新创建。如果你的默认参数是可变对象(比如list()、dict()这种),那所有没手动传参的函数调用,都会共享同一个可变对象实例。
就像你写的bfs/dfs方法:
def bfs(self, start, checked=[]): # 遍历逻辑... checked.append(start)
第一次调用时,checked用的是定义函数时创建的那个空列表,遍历完后这个列表里已经存了已访问的节点;第二次调用时,你没传checked,函数还是用那个已经被修改过的旧列表,自然会导致遍历逻辑出错,判断连通性返回错误结果。
修复方案
最优雅的解决办法是把默认参数设为None,然后在函数内部判断并初始化空列表:
def bfs(self, start, checked=None): # 如果没传checked,就创建一个新的空列表 if checked is None: checked = [] # 原来的遍历逻辑不变 if start not in checked: checked.append(start) # ... 后续的BFS逻辑
这样每次调用函数时,如果没手动传checked,都会生成一个全新的空列表,完全不会和之前的调用共享状态,彻底解决问题。
验证小例子
你可以用这个简单的代码直观感受这个陷阱:
def add_item(lst=[]): lst.append("item") print(lst) add_item() # 输出: ['item'] add_item() # 输出: ['item', 'item'] (共享了同一个列表) add_item([]) # 输出: ['item'] (手动传了新列表) add_item() # 输出: ['item', 'item', 'item'] (还是用原来的那个列表)
额外提示
不光是list,所有可变对象作为默认参数时都会有这个问题,比如dict()、自定义的可变类实例等等,都要用None+内部初始化的方式来规避。
内容的提问来源于stack exchange,提问作者Viktor Rozenko
相关产品推荐
相关产品推荐

