我已经编写了以下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
Run Code Online (Sandbox Code Playgroud)
如您所见,这两个函数都没有return语句。假设我要写这样的东西:
for p in primes_iterable():
if p > 1000:
break
print p
Run Code Online (Sandbox Code Playgroud)
break到达语句后,在内存级别会发生什么?如果我理解正确,调用primes_iterable()会使函数启动,直到下一个函数yield再暂停直到再次需要它为止。break到达该语句时,该函数实例是否关闭,或者它继续存在于后台,完全没有用?
您的函数primes_iterable是生成器函数。调用它时,不会立即发生任何事情(除了返回生成器对象之外)。只有在next被调用时,它才会运行到下一个yield。
调用generator函数时,将获得一个可迭代的generator对象。如果在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")
Run Code Online (Sandbox Code Playgroud)
这是一个示例运行:
>>> for i, s in enumerate(gen()):
print(s)
if i >= 3:
break
starting
foo
foo
foo
foo
caught GeneratorExit
cleaning up
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
107 次 |
| 最近记录: |