为什么要删除[1,3],[3,2]条目并将其替换为[2,3],[3,1]?
注意,[2,3],[3,1]是正确的分支,但它不应该覆盖前一个条目,它应该附加到它。
def rational():
treecount = 0
tree = [[[1,1]]]
left=[0,0]
right=[0,0]
while(True):
treecount+=1
tree.append([])
left=[0,0]
right=[0,0]
for z in range(len(tree[treecount-1])):
left[0] = tree[treecount-1][z][0]
right[0] = tree[treecount-1][z][0] + tree[treecount-1][z][1]
left[1] = tree[treecount-1][z][1] + tree[treecount-1][z][0]
right[1] = tree[treecount-1][z][1]
tree[treecount].append(left)
tree[treecount].append(right)
yield( tree)
输出如下:
[[[1, 1]], [[1, 2], [2, 1]]] [[[1, 1]], [[1, 2], [2, 1]], [[1, 3], [3, 2]]] [[[1, 1]], [[1, 2], [2, 1]], [[2, 3], [3, 1], [2, 3], [3, 1]]]
答案 0 :(得分:2)
你正在遇到Python对象模型的一个基本方面,即Python永远不会隐式地复制对象。
在您的代码中,您在进入left
循环之前创建了两个新列表right
和for
。然后,您反复修改这两个列表,并将它们附加到您的树中。这很好,除了你正在做的所有事情都是重复地附加对相同两个列表的引用。
这是一个更简单的例子。我们将创建一个列表left
并将其附加到另一个列表outer
:
>>> outer = []
>>> left = [1, 3]
>>> outer.append(left)
>>> outer
[[1, 3]]
到目前为止一切顺利:一切都像预期的那样。但现在让我们修改left
并再次将其附加到outer
:
>>> left[0] = 4
>>> outer.append(left)
>>> outer
[[4, 3], [4, 3]]
注意outer
的第一个条目是如何更改的?那是因为outer
此时不包含两个独立的列表:相反,它包含对相同列表的两个引用。这就是上面代码中发生的事情。
可以直接修复:在left
循环的每次迭代中重新创建right
和for
:
for z in range(len(tree[treecount-1])):
left=[0, 0]
right=[0, 0]
left[0] = tree[treecount-1][z][0]
right[0] = tree[treecount-1][z][0] + tree[treecount-1][z][1]
left[1] = tree[treecount-1][z][1] + tree[treecount-1][z][0]
<and so on>
或者,您可以在附加left
和right
之前制作副本:
tree[treecount].append(list(left))
tree[treecount].append(list(right))
顺便提一下,如果你更好地利用Python的一些习语,你可以大大简化你的代码。首先,迭代range(len(something))
通常是不必要的,特别是当您要将值直接用作索引时。直接在列表上迭代。其次,您可以直接在tree[treecount-1]
语句中解压缩for
值。然后,您可以使用负索引从列表末尾开始索引,从而节省维护treecount
的需要。通过这些首次更改,您的代码如下所示:
def rational():
tree = [[[1,1]]]
while True:
tree.append([])
for a, b in tree[-2]:
left = [a, b + a]
right = [a + b, b]
tree[-1].extend([left, right])
yield tree
仍有改进的余地,但这比原始代码更具可读性。
答案 1 :(得分:0)
如果您实际上不需要树,而只是想遍历正向理性,则可以使用此生成器。输出与Calkin-Wilf树的广度优先遍历顺序相同,但无需增加队列的开销。
from fractions import Fraction
def Calkin_Wilf():
x = Fraction(1, 1)
yield x
while True:
x = Fraction(1, 2*Fraction(int(x))-x+1)
yield x
使用生成器创建一个迭代器,然后使用next()进行迭代,例如:
rational = Calkin_Wilf()
for _ in range(100):
print(next(rational))