__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()
答案 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)
yield
在with
赢得了__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(..)
将抛出一个错误,即迭代用尽。