"Наконец" эквивалент для операторов If/Elif в Python
Имеет ли Python эквивалент finally
для своих операторов if/else
, аналогичный операторам try/except/finally
? Что-то, что позволит нам упростить это:
if condition1:
do stuff
clean up
elif condition2:
do stuff
clean up
elif condition3:
do stuff
clean up
...
...
:
if condition1:
do stuff
elif condition2:
do stuff
elif condition3:
do stuff
...
...
finally:
clean up
Где finally
будет вызываться только после того, как условие будет выполнено и будет выполняться его "делать материал"? И наоборот, если условие не было выполнено, код finally
не будет запущен.
Мне не терпит богохульства, но лучший способ я могу описать это, поскольку в конце каждого блока "do stuff" есть оператор GOTO
, который привел к finally
.
По существу, он работает как противоположность оператора else
. Пока else
запускается только при отсутствии других условий, это будет выполняться ТОЛЬКО, если будет выполнено другое условие.
Ответы
Ответ 1
Это можно сделать совершенно без взлома:
def function(x,y,z):
if condition1:
blah
elif condition2:
blah2
else:
return False
#finally!
clean up stuff.
В некотором смысле это не так удобно, поскольку вам нужно использовать отдельную функцию. Тем не менее, хорошая практика не делать слишком длинные функции в любом случае. Разделение вашей логики на небольшие легко читаемые (обычно максимум 1 страница) функции значительно облегчают тестирование, документирование и понимание потока выполнения.
Одна вещь, о которой нужно знать, это то, что предложение finally
не будет запущено в случае исключения. Для этого вам также нужно добавить материал try:
.
Ответ 2
Ваша логика сродни этому:
cleanup = True
if condition1:
do stuff
elif condition2:
do stuff
elif condition3:
do stuff
....
else:
cleanup = False
if cleanup:
do the cleanup
Уродливо, но это то, что вы просили
Ответ 3
Ответ mhlester имеет повторяющийся код, улучшенная версия может быть следующей:
class NoCleanUp(Exception):
pass
try:
if condition1:
do stuff
elif condition2:
do stuff
else:
raise NoCleanUp
except NoCleanUp:
pass
else:
cleanup
Ответ 4
Другое предложение, которое может подойти вам, если условия предварительно рассчитаны.
if condition1:
do stuff
elif condition2:
do stuff
...
if any([condition1, condition2, ...]):
clean_up
Это было бы больно, если бы вы оценивали условия как часть своих операторов if, потому что в этом случае вам пришлось бы их повторить во второй раз для функции any
... если Python не умнее, чем я понимаю.
Ответ 5
Немного поздно для вечеринки, но вижу, что вопрос был активен недавно.
Обычно я создавал бы такой контекстный менеджер
class CleanUp(object):
class Cancel(Exception):
pass
def __init__(self, f_cleanup):
self.f_cleanup = f_cleanup
def __enter__(self):
return self
def __exit__(self, exception_type, exception_value, traceback):
cancelled = exception_type and issubclass(exception_type, self.__class__.Cancel)
if not cancelled:
self.f_cleanup()
return not exception_type or cancelled
def cancel(self):
raise self.__class__.Cancel
И тогда вы можете использовать его так:
def cleanup():
print "Doing housekeeping"
with CleanUp(cleanup) as manager:
if condition1:
do stuff
elif condition2:
do stuff
else:
manager.cancel()
Ответ 6
Вы можете использовать попробовать
try:
if-elif-else stuff
finally:
cleanup stuff
Возникает исключение, но очистка выполнена
Ответ 7
Это отвратительно?
for _ in range(1):
if condition1:
do stuff
break
elif condition2:
do stuff
break
else:
finally stuff
Как насчет этого?
class NoFinally(Exception):
pass
try:
if condition1:
do stuff
raise NoFinally
elif condition2:
do stuff
raise NoFinally
except NoFinally:
pass
else:
finally
Честно говоря, я ненавижу обе эти
Ответ 8
Вот так:
from .actions import stuff1, stuff2
actions={condition1: stuff1, condition2: stuff2}
for condition in actions:
if condition:
actions[condition]()
cleanup()
break
Предупреждения, конечно же, означают, что ваши ключи условий должны быть уникальными и хешируемыми. Вы можете обойти это, используя другую структуру данных.