我想在某些条件下退出with
声明:
with open(path) as f:
print 'before condition'
if <condition>: break #syntax error!
print 'after condition'
当然,上述方法无效。有没有办法做到这一点? (我知道我可以颠倒这个条件:if not <condition>: print 'after condition'
- 任何方式都像上面那样?)
答案 0 :(得分:56)
with
给你带来麻烦?在这个问题上投入更多with
个能够对象!
class fragile(object):
class Break(Exception):
"""Break out of the with statement"""
def __init__(self, value):
self.value = value
def __enter__(self):
return self.value.__enter__()
def __exit__(self, etype, value, traceback):
error = self.value.__exit__(etype, value, traceback)
if etype == self.Break:
return True
return error
只需将您要转到with
的表达式与fragile
以及raise fragile.Break
打包,以便随时突破!
with fragile(open(path)) as f:
print 'before condition'
if condition:
raise fragile.Break
print 'after condition'
with
,只使用with
;不会将您的函数包装在语义上误导的一次性“循环”或一个狭隘的专用函数中,并且不会强迫您在with
之后执行任何额外的错误处理。嵌套!
with fragile(open(path1)) as f:
with fragile(open(path2)) as g:
print f.read()
print g.read()
raise fragile.Break
print "This wont happen"
print "This will though!"
这样,如果你想要破坏外部with
,你不必创建一个新函数来包装外部fragile
。
答案 1 :(得分:34)
最好的方法是将其封装在一个函数中并使用return
:
def do_it():
with open(path) as f:
print 'before condition'
if <condition>:
return
print 'after condition'
答案 2 :(得分:6)
我认为你应该只重构逻辑:
with open(path) as f:
print 'before condition checked'
if not <condition>:
print 'after condition checked'
答案 3 :(得分:5)
由于break
只能在循环内发生,因此您的选项会在with
内限制为:
如果你可以在一个函数中隔离return
和相关的语句(没有别的),那么拥有一个函数并使用with
可能是最干净最简单的解决方案。
否则,在需要时在with
内生成异常,立即抓住with
下方/外部以继续其余代码。
更新:正如OP在下面的评论中所暗示的那样(或许是脸颊?)还可以将with
语句包装在循环内以使break
起作用 - 虽然这在语义上会产生误导。因此,虽然是一个有效的解决方案,但可能不会推荐。)
答案 4 :(得分:3)
这是一个古老的问题,但这是一个方便易用范围的应用程序&#34;成语。只是将with
声明嵌入其中:
for _ in (True,):
with open(path) as f:
print 'before condition'
if <condition>: break
print 'after condition'
这个习语创建一个&#34;循环&#34;,总是只执行一次,其唯一目的是将一段代码封闭在一个可以有条件地破坏的范围内。在OP的情况下,它是一个被包含的上下文管理器调用,但它可能是任何可能需要条件转义的有界语句序列。
接受的答案很好,但是这种技术在不需要创建功能的情况下做同样的事情,这并不总是方便或不需要。
答案 5 :(得分:2)
f = open("somefile","r")
for line in f.readlines():
if somecondition: break;
f.close()
我认为你不能突破......你需要使用循环...
[编辑]或只是做其他人提到的功能方法
答案 6 :(得分:2)
为此目的存在函数__exit__()
。语法如下:
with VAR = EXPR:
try:
BLOCK
finally:
VAR.__exit__()
答案 7 :(得分:1)
你可以把所有东西放在一个函数中,当条件为真时,调用一个返回。
答案 8 :(得分:1)
作为速记摘录:
class a:
def __enter__(self):
print 'enter'
def __exit__(self ,type, value, traceback):
print 'exit'
for i in [1]:
with a():
print("before")
break
print("after")
...
enter
before
exit
答案 9 :(得分:0)
从“休息”更改为“关闭”
with open(path) as f:
print('before condition')
if <condition>: f.close()
print('after condition')
答案 10 :(得分:0)
使用97MiB
:
python3 -c "x = 'a' * (2 * 10 ** 8)"
答案 11 :(得分:0)
这是使用try
和except
的另一种方法,即使反转条件可能更方便。
class BreakOut(Exception): pass
try:
with open(path) as f:
print('before condition')
if <condition>:
raise BreakOut #syntax error!
print('after condition')
except BreakOut:
pass