Python树形结构递归对象引用异常问题求助
问题根源:类属性与实例属性的共享陷阱
嘿,我一眼就揪出问题所在了——你踩了Python类属性和实例属性混淆的坑!
在你的PathElement类里,Children = []是定义在类级别的属性,这意味着所有PathElement的实例都会共享同一个列表对象,而不是每个实例拥有自己独立的子节点列表。
举个直白的例子:当你给root添加child1时,是往这个共享列表里加child1;接着给child1添加child2时,还是往同一个共享列表里加child2;到最后,所有节点的Children属性都指向同一个装满了所有节点的列表。这就导致你遍历树形结构时,会从child1的子节点里又拿到child1(因为共享列表的第一个元素是child1),直接陷入无限循环。
修复方案:把类属性改成实例属性
只需要把类级别的属性移到__init__方法里,用self.xxx定义为实例属性,让每个节点拥有自己独立的状态:
class PathElement: def __init__(self, Element, IsStatic=True): self.Element = Element self.IsStatic = IsStatic self.Children = [] # 每个实例独享的子节点列表 self.ChildrenCount = 0 if not IsStatic: self.Element = [] def AddChild(self, Child): print(self, " ", Child) self.Children.append(Child) self.ChildrenCount = len(self.Children) return Child
修改后,每个PathElement实例都会拥有自己的Children列表,添加子节点时只会加到当前节点的专属列表里,树形结构就能按照你的预期生成了——root→child1→child2→child3…依次向下,不会出现循环。
你可以用自己的简化测试代码验证一下:运行后会依次打印root、child1、child2、child3、child4、child5,然后正常退出循环,完全符合预期。
小提醒
Python里,类定义直接声明的变量是类属性,属于整个类,所有实例共享;而通过self.xxx声明的是实例属性,每个实例各自拥有独立的副本。如果需要每个对象维护自己的状态(比如树节点的子节点列表),一定要用实例属性哦!
内容的提问来源于stack exchange,提问作者Ahmad Issa

