"产生" -ing触发__exit__功能,如果在""内完成的话。块?

时间:2017-02-15 19:35:52

标签: python

来自__exit__区块内的

This question as been asked with respect to returning,但屈服怎么样?

如果下一次调用该函数,是否会在yield上调用块__enter__然后再次调用def tmp_csv_file(): tmp_path = 'tmp.csv' with open(tmp_path, 'w+') as csv_file: yield csv_file # will this close the file? os.remove(tmp_path) ?或者是否等待生成器退出with块(或返回)

作为一个例子:

from("servlet:/receive").streamCaching()

4 个答案:

答案 0 :(得分:3)

让我们凭经验测试一下。

class MyContextManager:
    def __enter__(self):
        pass
    def __exit__(self, *args):
        print "Context manager is exiting."


def f():
    print("Entered Function.")
    with MyContextManager() as m:
        print("Entered with statement. Yielding...")
        yield m
        print("Yielded. About to exit with statement.")
    print("Now outside of with statement.")

for x in f():
    pass

输出:

C:\Users\Kevin\Desktop>test.py
Entered Function.
Entered with statement. Yielding...
Yielded. About to exit with statement.
Context manager is exiting.
Now outside of with statement.

“关于退出with语句”消息后出现“上下文管理器正在退出”消息,因此我们可以得出结论yield语句触发{{1}方法。

答案 1 :(得分:3)

取决于:

  • 如果您的生成器功能超出范围(或以其他方式删除),则会调用messages

  • 如果生成器耗尽,则调用__exit__

=>只要生成器处于有效块且未耗尽且未保留生成器的变量,则不会调用__exit__

例如:

__exit__

测试它:

class Test(object):
    def __init__(self):
        print('init')

    def __enter__(self):
        print('enter')

    def __exit__(self, *args, **kwargs):
        print('exit')


def funfunc():
    with Test():
        yield 1
        yield 2

或者如果手动删除:

>>> a = funfunc()
>>> next(a)  # no exit
init
enter
1
>>> next(a)  # no exit
2
>>> next(a, 0)  # exit because generator leaves the with-context inside the function
exit
0

答案 2 :(得分:2)

yieldwith赢得了__exit__内。生成器内的控制流必须离开with块以使__exit__触发;暂停生成器并不算作离开with块。这在精神上类似于上下文切换到另一个线程也不会触发__exit__

答案 3 :(得分:0)

简而言之:没有,它会从到达yield语句的那一刻起暂停该方法。如果您要求下一个元素,则执行余数。

鉴于你写了result = tmp_csv_file() 没有做任何事情:所以甚至不执行tmp_path='tmp.csv'

现在,如果您致电next(result),Python将开始评估函数,直到它到达第一个yield语句。因此,它会执行文件tmp_path = 'tmp.csv'open(..)和环境__enter__。它命中yield语句,因此返回csv_file。现在,您可以使用该文件执行任何操作。该文件将保持打开状态(只要您没有明确close()),__exit__ 不会被调用

如果您再次致电next(result) ,Python将继续寻找下一个yield声明。因此__exit__环境with,并删除文件(os.remove(tmp_path))。然后它命中方法的结尾。这意味着我们已经完成了。因此next(..)将抛出一个错误,即迭代用尽。