【问题标题】:Will the generator be closed automatically after fully iteration?完全迭代后生成器会自动关闭吗?
【发布时间】:2020-07-16 09:50:51
【问题描述】:

一定要写吗

def count10():
    for i in range(10):
        yield i
gen = count10()
for j in gen:
    print(j)
gen.close()

为了节省内存,或者只是

def count10():
    for i in range(10):
        yield i
for j in count10():
    print(j)

其实我很想了解 Python 生成器的生命周期细节,但是没找到相关资源。

【问题讨论】:

    标签: python generator


    【解决方案1】:

    你不需要close那个生成器。

    close-ing 生成器不是为了节省内存。 (close-ing 事情几乎从不涉及节省内存。)生成器上 close 方法背后的想法是,您可能会在生成器仍在 trywith 中间时停止迭代:

    def gen():
        with something_important():
            yield from range(10)
    
    for i in gen():
        if i == 5:
            break
    

    close-ing 暂停的生成器将GeneratorExit 异常抛出到生成器中,目的是触发finally 块和上下文管理器__exit__ 方法。这里,close 将导致生成器运行something_important()__exit__ 方法。如果您没有像这样在中间放弃生成器(或者如果您的生成器没有任何finallywith 块,包括在它委托给yield from 的生成器中),那么close 是不必要的(并且什么都不做)。

    内存管理系统通常会为您运行 close,但要真正确保在 Python 实现中迅速关闭,您必须替换类似的代码

    for thing in gen():
        ...
    

    with contextlib.closing(gen()) as generator:
        for thing in generator:
            ...
    

    我从未见过有人这样做。

    【讨论】:

      【解决方案2】:

      生成器的close 方法出现在PEP 342

      为生成器迭代器添加一个 close() 方法,该方法在生成器暂停时引发 GeneratorExit。如果生成器随后引发 StopIteration(通过正常退出,或由于已经关闭)或 GeneratorExit(通过不捕获异常),则 close() 返回其调用者。如果生成器产生一个值,则会引发 RuntimeError。如果生成器引发任何其他异常,则会将其传播给调用者。如果生成器由于异常或正常退出而已经退出,则 close() 不执行任何操作。

      注意最后一句:close() 如果生成器由于异常或正常退出而已经退出,则不执行任何操作。

      【讨论】:

        猜你喜欢
        • 2011-04-01
        • 2016-12-07
        • 2015-06-08
        • 2012-03-16
        • 1970-01-01
        • 1970-01-01
        • 2020-01-29
        • 1970-01-01
        相关资源
        最近更新 更多