这个 "while True" 循环是如何结束的?

How does this "while True" loop end?

考虑这段代码:

from random import randrange
from contextlib import suppress

mybiglist = [randrange(1, 100) for i in range(1000)]
count = 0
with suppress(ValueError):
    while True:
        mybiglist.remove(1)
        count += 1
print("Count of 1's is : %d "% count)

我没有放置任何 break 语句来结束这个循环。 我无法理解此 "while True" 循环如何以及为何终止? 当它发现没有更多的匹配元素要删除时,它神奇地中断了! 怎么样?

例如:

from random import randrange
from contextlib import suppress

mybiglist = [randrange(1, 100) for i in range(1000)]
count = 0

with suppress(ValueError):
    while True:
        mybiglist.remove(222)  # a number outside of the randrange, so zero occurrence
        count += 1
print("Count of 222's is : %d "% count)

正确打印

Count of 222's is : 0 

考虑到计数甚至没有达到值“1”,很明显 list.remove() 导致 while 循环中断。

但是 list.remove 的文档只是指出:

list.remove(x) : Remove the first item from the list whose value is equal to x. It raises a ValueError if there is no such item.

并且我已经抑制了 ValueError。那么这里发生了什么?

以下变体 没有抑制 确实按预期工作并以无限循环结束。

from random import randrange

mybiglist = [randrange(1, 100) for i in range(1000)]
count = 0

while True:
    try:
        mybiglist.remove(222)
        count += 1
    except ValueError:
        pass

print("Count of 222's is : %d "% count)

删除不存在的元素会引发错误。该错误将停止循环,并且由于您在外部抑制了它,因此抑制后代码继续:

with suppress(ValueError):
    while True:
        mybiglist.remove(222) # element that doesn't exist, raises error
        count += 1
# ... code continues here

如果希望循环继续,则必须在错误传播到循环之前抑制错误:

while True:
    with suppress(ValueError):
        mybiglist.remove(222) # element that doesn't exist, raises error
        count += 1
    # ... code continues here

这意味着循环将继续 运行 即使出现错误。

您的代码正在抑制结束循环的错误。您的循环最终无法从 biglist 中删除另一个值并抛出您已抑制的 ValueError,因此循环以对您来说看似干净的方式结束。如果您删除 with suppress(ValueError):,您将看到以下内容:ValueError: list.remove(x): x not in list