Ответ 1
Лучшим способом было бы инкапсулировать его в функцию и использовать return
:
def do_it():
with open(path) as f:
print 'before condition'
if <condition>:
return
print 'after condition'
Я бы просто хотел выйти из инструкции with
при определенных условиях:
with open(path) as f:
print 'before condition'
if <condition>: break #syntax error!
print 'after condition'
Конечно, вышесказанное не работает. Есть ли способ сделать это? (Я знаю, что я могу инвертировать условие: if not <condition>: print 'after condition'
- любым способом, как указано выше?)
Лучшим способом было бы инкапсулировать его в функцию и использовать return
:
def do_it():
with open(path) as f:
print 'before condition'
if <condition>:
return
print 'after condition'
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
, и вам хорошо идти!Я думаю, вам нужно просто перестроить логику:
with open(path) as f:
print 'before condition checked'
if not <condition>:
print 'after condition checked'
Так как break
может возникать только внутри цикла, ваши параметры несколько ограничены внутри with
до:
Наличие функции и использование return
, вероятно, самое чистое и простое решение здесь, если вы можете изолировать with
и связанные с ним операторы (и ничего больше) внутри функции.
В противном случае создайте исключение внутри with
, если необходимо, поймайте ниже/вне with
, чтобы продолжить остальную часть кода.
Обновление: Как предлагает OP в комментариях ниже (возможно, tonuge в щёке?), можно также обернуть оператор with
внутри цикла, чтобы заставить break
работать, хотя это было бы семантически вводить в заблуждение. Поэтому, хотя рабочее решение, вероятно, не то, что было бы рекомендовано).
Вы можете поместить все внутри функции, а когда условие истинно, вызовите возврат.
f = open("somefile","r")
for line in f.readlines():
if somecondition: break;
f.close()
Я не думаю, что вы можете вырваться из-за... вам нужно использовать цикл...
[edit] или просто используйте метод функции, упомянутый другими
как сокращенный фрагмент:
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
Это древний вопрос, но это приложение для удобной идиомы "разрываемой видимости". Просто вставьте свой оператор with
внутри:
for _ in (True,):
with open(path) as f:
print 'before condition'
if <condition>: break
print 'after condition'
Эта идиома создает "цикл", всегда выполняемый ровно один раз, с единственной целью - заключить блок кода внутри области действия, который может быть разбит условно. В случае OP это был вызов диспетчера контекста, который должен быть заключен, но это может быть любая ограниченная последовательность операторов, которая может потребовать условного выхода.
Принятый ответ в порядке, но этот метод делает то же самое без необходимости создавать функцию, которая не всегда удобна или желательна.