class ContinueI(Exception):
pass
continue_i = ContinueI()
for i in ...:
try:
for j in ...:
for k in ...:
if something:
raise continue_i
except ContinueI:
continue
for ii in range(200):
for jj in range(200, 400):
...block0...
if something:
break
...block1...
例如,下面是一段简单的代码,可以看到它到底是如何运行的:
for i in range(10):
print("doing outer loop")
print("i=",i)
for p in range(10):
print("doing inner loop")
print("p=",p)
if p==3:
print("breaking from inner loop")
break
print("doing some code in outer loop")
for i in range(0, 6):
should_continue = False
for f in range(1, i * 2):
print(f"f = {f}")
if (not (f % 1337) or not (f % 7)):
print(f"{f} can be divided, continue outer loop")
should_continue = True
# leaves inner loop
break
if(should_continue): continue
# Outer loop's code goes here
print(f'Reached outer loop\ni = {i}')
这种方法避免调用任何函数和处理可能的缺点。众所周知,调用函数是一个相当昂贵的操作,特别是对 Games 而言。现在想象一个深度嵌套的 for循环将运行数百万次,将其包装在函数中不会导致平滑的体验。
将循环包装在异常块中也是一个糟糕的主意,而且会比函数慢得多。这是因为 Python 需要大量的开销来触发异常机制,并在以后恢复运行时状态,因此异常被设计为在特殊情况下使用。考虑到这一点,即使是一些 CPU 优化,如 speculative execution,也不应该应用于异常块,而且可能不会。
我在这种方法中发现的唯一“问题”是,break会跳出内环一次,落在 continue上,而 continue又会再跳一次。与 C 或 JavaScript 中的 goto 语句不同,这个语句有点笨拙,但对性能没有任何明显影响,因为它只会生成一条额外的指令,其运行速度与 CPU 的时钟或解释器实现一样快。