我正在尝试浏览一个在循环期间正在增长的列表。对于较大的列表,我遇到一个奇怪的行为,迭代在遍历所有元素之前停止:
from blist import sortedlist
# for-loop
l = sortedlist(range(400))
for x in l:
print(x)
if x % 10 == 0:
l.add(max(l) + 1)
print('last element:', l[-1])
# while-loop
l = sortedlist(range(400))
k = 0
while True:
try:
print(l[k])
if l[k] % 10 == 0:
l.add(max(l) + 1)
k = k + 1
except IndexError:
break
print('last element:', l[-1])
结果:
.
.
.
430
431
last element: 443
.
.
.
443
444
last element: 444
普通列表不会发生这种情况。而“while-loop”会按照我的要求遍历所有元素。我认为sortedlist
存储为树结构,并且在循环期间修改列表时它不能很好地运行,但是如果有人对此有更多的了解(和/或更清晰/更好的方式来获得相同的行为)而不是“while-loop”)
请注意,它不是一个关键部分,因此我不介意“while-loop”情况下的log(n)访问成本。
答案 0 :(得分:2)
原因很简单。在集合上创建foreach循环时,循环将保留其迭代的列表信息的本地副本。这意味着它只迭代原始列表的长度(不考虑任何修改)。
while循环只检查每次迭代的条件是否为真,并且不保留列表信息的本地副本。
根据你的评论,我试图重现它,但没有成功。然而,这似乎产生了你想要的东西:
l = sorted(range(400))
for x in l:
print x
if x%10 == 0:
l.append(max(l)+1)
print str(l[-1])