[英]Rational number generator (Python)
为什么要删除[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]]]
您正在遇到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))
迭代,尤其是当您要直接使用这些值作为索引时。 而是直接在列表上进行迭代。 其次,您可以直接在for
语句中解压tree[treecount-1]
值。 然后,您可以使用负索引从列表末尾开始索引,从而无需维护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
仍有改进的空间,但这已经比原始代码更具可读性。
如果您实际上不需要树,而只是想遍历积极的理性,则可以使用此生成器。 输出与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))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.