提问人:Cherry Toska 提问时间:6/29/2023 更新时间:7/3/2023 访问量:19
Python 中树迭代中的一些问题,而树可以动态生成
Some Issues in Tree Iteration in Python while the Tree Can be Dynamically Generated on the Fly
问:
我正在编写以下功能。一个根节点有 2 组索引(_indices_lhs 和 _indices_rhs),在左侧和右侧的每个索引之前,它都会创建一个子节点,其中
例如,ik、kn 将有一个子项,其中子项的 _indices_lhs 和 _indices_rhs 分别为 i 和 n。例如,在 ikn、ikn(左右两侧的相同索引)的情况下,预期结果是您将有 3 个孩子 kn, kn;在,在;IK、IK 和 OFC 这 3 个孩子将各多生 2 个孩子。为了实现这一点,我用一个while循环来迭代树。我将创建根节点,然后保留已创建子节点的引用队列,然后只要此队列不为空,我就会进行迭代,以创建可能创建节点的更多子节点/节点。当我遍历所有队列并且它是空的时,我就可以知道不能再生成子项了。我为此目的实现的代码如下:
该节点如下所示,子节点是在成员函数generate_further_paths中创建的。我创建所有可能的子组合,并将它们添加到成员变量_children。
class Node:
_parent = None
_depth = 0
_indices_lhs = list()
_indices_rhs = list()
_children_contractions = list()
_children = list()
def __init__(self, indices_lhs: list[str], indices_rhs: list[str], depth: int = 0):
self._indices_lhs = indices_lhs
self._indices_rhs = indices_rhs
self._depth = depth
print(self)
def generate_further_paths(self):
if len(self._indices_lhs) == 0 or len(self._indices_rhs) == 0:
return
if len(self._indices_lhs) == 1 and len(self._indices_rhs) == 1 \
and self._indices_lhs[0] == self._indices_rhs[0]:
return
print("D1: ", self._depth, ": ", self._indices_lhs, " | ", self._indices_rhs)
intersected_indices = []
for i in self._indices_lhs:
if i in self._indices_rhs:
intersected_indices.append(i)
if len(intersected_indices) == 0:
return
print("Intersected indices: ", intersected_indices)
for ii in intersected_indices:
child_lhs = copy.deepcopy(self._indices_lhs)
child_lhs.remove(ii)
child_rhs = copy.deepcopy(self._indices_rhs)
child_rhs.remove(ii)
child = Node(child_lhs, child_rhs, self._depth + 1)
self._children_contractions.append(ii)
self._children.append(copy.deepcopy(child))
def __str__(self):
return f"Node constructed depth {self._depth}:" + "".join(self._indices_lhs) + " * " + \
"".join(self._indices_rhs) + ", " + str(len(self._children)) + " children"
def __repr__(self):
return '<tree node representation>'
生成树的循环方法如下。我正在尝试确保队列元素是对原始元素的引用:
free_lhs = ["i", "k", "n"]
free_rhs = ["i", "k", "n"]
beginNode = Node(free_lhs, free_rhs, 0)
beginNode.generate_further_paths()
queue = copy.copy(beginNode._children)
while len(queue) != 0:
nq = list()
for child in queue:
child.generate_further_paths()
nnq = copy.copy(child._children)
nq += nnq
queue = nq
我认为有些事情我理解发生了一些错误,因为在这个循环中我不断获得更多元素,并且树中的一些节点增加了它们的子节点的数量。输出示例:
D1: 1 : ['i', 'k'] | ['i', 'k']
Intersected indices: ['i', 'k']
Node constructed depth 2:k * k, 4333 children
Node constructed depth 2:i * i, 4334 children
但是在深度 2 处构造的节点永远不会在生成时迭代,但它们的子节点会不断推回其成员变量_children。我更多地来自 C++ 领域,并且有参考,我认为这不应该发生,所以我认为这里的东西没有通过引用来捕获。
由于名称与真实对象绑定,因此我希望这种方法不会成为问题。我迭代每个子项,用生成的子项列表覆盖上一个队列。我需要一些关于我的代码行为的进一步见解,因为我已经阅读了这篇文章。 以及其他一些来源,但我无法掌握它。
答:
我想发布@slothrop的评论作为答案,因为它解决了问题。
self._children = list()
创建一个类变量,该变量在类的每个实例上共享。成员变量需要在类的方法中初始化。 __init__
上一个:关于C语言中按值调用的问题
评论
self._children
将是您定义的类变量,而不是实例变量。是否要在方法中初始化为实例变量?事实上,我怀疑你在这里不需要任何类变量,所有的类变量实际上都应该是实例变量。self._children = list()
__init__