我正在尝试用各种方法在Python中创建无限循环(除了通常的2019-01-22 13:29:32.897893-0800 test[86762:4812871] Starting <MyOperation: 0x10058d2d0>
2019-01-22 13:29:32.897893-0800 test[86762:4812872] Starting <MyOperation: 0x10058d710>
2019-01-22 13:29:32.897903-0800 test[86762:4812873] Starting <MyOperation: 0x100589930>
2019-01-22 13:29:32.898161-0800 test[86762:4812871] Starting <MyOperation: 0x10058edc0>
2019-01-22 13:29:32.898166-0800 test[86762:4812873] Starting <MyOperation: 0x10058ed50>
2019-01-22 13:29:37.898487-0800 test[86762:4812872] Finished <MyOperation: 0x100589930>
2019-01-22 13:29:37.898489-0800 test[86762:4812870] Finished <MyOperation: 0x10058ed50>
2019-01-22 13:29:37.898548-0800 test[86762:4812874] Finished <MyOperation: 0x10058edc0>
2019-01-22 13:29:37.898797-0800 test[86762:4812870] Starting <MyOperation: 0x100590000>
2019-01-22 13:29:37.899160-0800 test[86762:4812870] Finished <MyOperation: 0x10058d710>
2019-01-22 13:29:37.899651-0800 test[86762:4812870] Starting <MyOperation: 0x1005901a0>
2019-01-22 13:29:37.899933-0800 test[86762:4812874] Starting <MyOperation: 0x100590340>
2019-01-22 13:29:37.900133-0800 test[86762:4812871] Finished <MyOperation: 0x10058d2d0>
2019-01-22 13:29:37.900504-0800 test[86762:4812871] Starting <MyOperation: 0x100590680>
2019-01-22 13:29:37.900583-0800 test[86762:4812874] Starting <MyOperation: 0x1005904e0>
2019-01-22 13:29:42.899325-0800 test[86762:4812871] Finished <MyOperation: 0x100590000>
2019-01-22 13:29:42.899541-0800 test[86762:4812874] Starting <MyOperation: 0x100590820>
2019-01-22 13:29:43.393291-0800 test[86762:4812871] Finished <MyOperation: 0x1005901a0>
2019-01-22 13:29:43.393298-0800 test[86762:4812874] Finished <MyOperation: 0x100590340>
2019-01-22 13:29:43.394531-0800 test[86762:4812874] Finished <MyOperation: 0x1005904e0>
2019-01-22 13:29:43.395380-0800 test[86762:4812874] Finished <MyOperation: 0x100590680>
2019-01-22 13:29:43.396359-0800 test[86762:4812874] Starting <MyOperation: 0x1005909c0>
2019-01-22 13:29:43.397440-0800 test[86762:4812872] Starting <MyOperation: 0x100590b60>
2019-01-22 13:29:43.397891-0800 test[86762:4812874] Starting <MyOperation: 0x100590d00>
2019-01-22 13:29:43.399711-0800 test[86762:4812872] Starting <MyOperation: 0x100590ea0>
2019-01-22 13:29:47.900058-0800 test[86762:4812984] Finished <MyOperation: 0x100590820>
2019-01-22 13:29:48.892953-0800 test[86762:4812872] Finished <MyOperation: 0x100590d00>
2019-01-22 13:29:48.892970-0800 test[86762:4812871] Finished <MyOperation: 0x100590b60>
2019-01-22 13:29:48.893019-0800 test[86762:4813163] Finished <MyOperation: 0x100590ea0>
2019-01-22 13:29:48.893562-0800 test[86762:4812984] Finished <MyOperation: 0x1005909c0>
Program ended with exit code: 0
以外),并提出了这个想法:
while True
在纸上,我找出了无限循环的方式:
x = {0: None}
for i in x:
del x[i]
x[i+1] = None # Value doesn't matter, so I set it to None
print(i)
中当前的计数器位置将是值为+ 1
的新关键字,它将更新字典。在我看来,这应该以一种无限循环的方式输出自然数:
None
我认为这个想法很聪明,但是当我在Python 3.6上运行它时,它的输出是:
0
1
2
3
4
5
.
.
.
是的,它在5次迭代后以某种方式停止了。显然,循环的代码块中没有基本条件或哨兵值,那么Python为什么只运行该代码5次?
答案 0 :(得分:43)
如果您在循环中对其进行了突变,则不能保证将迭代所有dict条目。来自docs:
在添加或删除字典中的条目时迭代视图可能 引发RuntimeError或无法遍历所有条目。
您可以使用Flowable.create<Int>({ emmit ->
loadNewListener = object :Listener {
override fun onEmit(id: Int) {
emmit.onNext(id)
}
}
}, BackpressureStrategy.LATEST)
.debounce(500, TimeUnit.MILLISECONDS)
.subscribe({
loadNew(id = it.id)
}, {
Timber.e("")
})
创建一个类似于您初次尝试的“枚举”无限循环。例如:
itertools.count()
答案 1 :(得分:8)
在这种情况下,就像@benvc所写的那样,这不能保证能正常工作。但是,如果您想知道为什么它不能在C-Python中工作:
在一些插入并将其复制到内存中的新空间之后,C-Python实现销毁dict对象。它不关心删除。因此,当发生这种情况时,循环会注意到它并中断异常。
如果您想了解更多有关此内容以及此处其他许多有趣的python内部信息的信息,请查看此链接。
https://github.com/satwikkansal/wtfpython#-modifying-a-dictionary-while-iterating-over-it
答案 2 :(得分:5)
我刚刚在python2和python3中测试了您的代码
python3 output
0,1,2,3,4
python2
0,1,2,3,4,5,6,7
我想到可能正在发生的一件事。创建第一个键值时,词典中只会分配一定数量的内存,而删除键值时,我们不会分配任何内存,也不会释放内存,而只是删除该值。一旦所有分配的内存都用完,它将退出。因为如果您在没有该del的情况下运行,则会收到此错误
RuntimeError: dictionary changed size during iteration
因此python为该键值创建了足够的内存,并为它创造了更多的内存,一旦用完,就不会再为字典分配更多的内存了。
答案 3 :(得分:3)
许多人指出,在迭代过程中使用for
循环修改数据结构不是一个好主意。 while
循环确实允许这样做,因为它在每次迭代时都会重新评估其循环条件(令人印象深刻的是,还没有人建议这样做)。只需找到正确的循环条件即可。您的脚本必须变成:
x = {0: None}
while x:
i, _ = x.popitem()
print(i)
# to avoid infinite loop while testing
# if i == 10:
# break
x[i+1] = None
在Python中,字典为空时是虚假的(请参见docs),因此仅当迭代x
为空时,循环才会停止。
由于字典只有一对键值对,因此popitem()
应该足以获取该对并将其从字典中删除。由于在清空字典后立即添加下一个整数,因此求值时循环条件永远不会为假,从而导致无限循环。