Lig*_*eze 222 python return with-statement
考虑以下:
with open(path, mode) as f:
return [line for line in f if condition]
Run Code Online (Sandbox Code Playgroud)
文件是否会正确关闭,或者以return
某种方式绕过上下文管理器?
Thi*_*ter 202
是的,它就像一个finally
块之后的try
块,即它总是执行(除非python进程以一种不寻常的方式终止).
在PEP-343的一个例子中也提到了它,它是with
声明的规范:
with locked(myLock):
# Code here executes with myLock held. The lock is
# guaranteed to be released when the block is left (even
# if via return or by an uncaught exception).
Run Code Online (Sandbox Code Playgroud)
值得一提的是,你不能轻易地捕获open()
调用引发的异常,而不是将整个with
块放在一个try..except
通常不是你想要的块中.
dbr*_*dbr 30
是.
def example(path, mode):
with open(path, mode) as f:
return [line for line in f if condition]
Run Code Online (Sandbox Code Playgroud)
..几乎相当于:
def example(path, mode):
f = open(path, mode)
try:
return [line for line in f if condition]
finally:
f.close()
Run Code Online (Sandbox Code Playgroud)
更准确地说,__exit__
在退出块时总是调用上下文管理器中的方法(无论异常,返回等).文件对象的__exit__
方法只是调用f.close()
(例如在CPython中)
Acu*_*nus 18
是.更一般地说,在语境内部确实会调用With语句上下文管理器的__exit__
方法.可以使用以下方法测试:return
class MyResource:
def __enter__(self):
print('Entering context.')
return self
def __exit__(self, *exc):
print('EXITING context.')
def fun():
with MyResource():
print('Returning inside with-statement.')
return
print('Returning outside with-statement.')
fun()
Run Code Online (Sandbox Code Playgroud)
输出是:
Entering context.
Returning inside with-statement.
EXITING context.
Run Code Online (Sandbox Code Playgroud)
上面的输出确认了__exit__
尽管早期被调用return
.因此,上下文管理器不会被绕过.
是的,但在其他情况下可能会有一些副作用,因为它可能应该在__exit__
块中执行某些操作(例如刷新缓冲区)
import gzip
import io
def test(data):
out = io.BytesIO()
with gzip.GzipFile(fileobj=out, mode="wb") as f:
f.write(data)
return out.getvalue()
def test1(data):
out = io.BytesIO()
with gzip.GzipFile(fileobj=out, mode="wb") as f:
f.write(data)
return out.getvalue()
print(test(b"test"), test1(b"test"))
# b'\x1f\x8b\x08\x00\x95\x1b\xb3[\x02\xff' b'\x1f\x8b\x08\x00\x95\x1b\xb3[\x02\xff+I-.\x01\x00\x0c~\x7f\xd8\x04\x00\x00\x00'
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
40511 次 |
最近记录: |