"Наконец" эквивалент для операторов 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

Предупреждения, конечно же, означают, что ваши ключи условий должны быть уникальными и хешируемыми. Вы можете обойти это, используя другую структуру данных.