我编写了以下 python 函数:
import numpy
def primes_iterable():
"""Iterable giving the primes"""
# The lowest primes
primes = [2,3,5]
for p in primes:
yield p
for n in potential_primes():
m = int(numpy.sqrt(n))
check = True
for p in primes:
if p > m:
break
if n%p == 0:
check = False
if check:
primes.append(n)
yield n
def potential_primes():
"""Iterable starting at 7 and giving back the non-multiples of 2,3,5"""
yield 7
n = 7
gaps = [4,2,4,2,4,6,2,6]
while 1:
for g in gaps:
n += g
yield n
如您所见,这两个函数都没有return 语句。假设我要写这样的东西:
for p in primes_iterable():
if p > 1000:
break
print p
当到达break 语句时,内存级别会发生什么?如果我理解正确,调用 primes_iterable() 会使函数启动,直到下一个 yield 然后暂停直到再次需要它。当执行到break语句时,函数实例是关闭,还是继续存在于后台,完全没用?
请您参考如下方法:
您的函数 primes_iterable 是一个生成器函数。当您调用它时,不会立即发生任何事情(除了返回一个生成器对象)。只有当 next 被调用时,它才会运行到下一个 yield。
当你调用生成器函数时,你会得到一个可迭代的生成器对象。如果您在 for 循环中这样做,循环将在运行时保留对生成器对象的引用。如果您break 退出循环,该引用将被释放并且生成器对象可以被垃圾回收。
但是当生成器对象被清除时,生成器函数中运行的代码会发生什么?它被 GeneratorStop 异常中断,该异常在它暂停的 yield 处被抛出。如果需要,您可以让生成器函数捕获此异常,但除了清理资源和退出之外,您不能做任何有用的事情。这通常是通过 try/finally 对来完成的,而不是 except 语句。
下面是一些演示该行为的示例代码:
def gen():
print("starting")
try:
while 1:
yield "foo"
except GeneratorExit:
print("caught GeneratorExit")
raise
finally:
print("cleaning up")
这是一个示例运行:
>>> for i, s in enumerate(gen()):
print(s)
if i >= 3:
break
starting
foo
foo
foo
foo
caught GeneratorExit
cleaning up
