类变量重置后值仍保留?Python类成员变量生命周期疑问
问题:类级列表属性导致多次调用结果污染的原因
先看这段会在不同二叉树上多次执行的代码:
class Solution: ans = [] def getLonelyNodes(self, root: Optional[TreeNode]) -> List[int]: def helper(root): if root.left is None and root.right: self.ans.append(root.right.val) return helper(root.right) if root.left and root.right is None: self.ans.append(root.left.val) return helper(root.left) if root.left and root.right: return helper(root.left), helper(root.right) if root.left is None and root.right is None: return helper(root) ans = self.ans self.ans = [] return ans
问题是:虽然在函数末尾重置了self.ans,但下次运行时结果里仍会保留之前的值,每次运行都会把旧结果追加到新结果里。把self.ans = []移到helper函数上方后问题解决了,但不明白为什么开头重置有效,末尾重置无效。
原因解析
核心问题出在类属性和实例属性的区别上:
- 你定义的
ans = []是类级别的属性,所有Solution类的实例都会共享这个列表对象,本质是一个全局共享的容器。 - 当你第一次调用
getLonelyNodes时:self.ans会先找当前实例有没有ans属性,因为实例没有,所以直接使用类的ans列表,往里面追加元素。- 函数末尾执行
self.ans = [],这一步是给当前实例新增了一个名为ans的实例属性,值是空列表,但类本身的ans列表还是原来那个存了旧结果的对象。
- 如果下次调用时是创建了新的
Solution实例:
新实例没有自己的ans属性,会去读取类的ans,也就是之前被污染的那个旧列表,所以新结果会和旧结果混在一起。
而把self.ans = []移到函数开头后:
- 每次调用
getLonelyNodes时,都会先给当前实例绑定一个全新的空列表作为ans属性,后续self.ans.append()操作的都是这个实例自己的列表,和类的共享列表彻底无关。 - 不管是同一个实例多次调用,还是创建新实例调用,每次操作的都是独立的空列表,自然不会出现旧结果残留的问题。
简单来说:末尾重置只是给当前实例“换了个新列表”,但类的共享列表没被清空;开头重置是每次都用实例自己的新列表,完全避开了类的共享属性。
内容的提问来源于stack exchange,提问作者Alec
相关产品推荐
相关产品推荐

