Я уверен, что эта концепция возникла раньше, но я не могу найти хороший, простой ответ. Является ли использование try / finally плохим способом обработки функций с множественным возвратом? Например у меня


try:
    if x:
        return update(1)
    else:
        return update(2)
finally:
    notifyUpdated()

Это выглядит лучше, чем хранить команды update () во временной переменной и возвращать ее.

5
Falmarri 17 Авг 2010 в 01:08

6 ответов

Лучший ответ

Я бы не рекомендовал это. Во-первых, потому что notifyUpdated() будет вызван, даже если код в любой ветви выдает исключение. Вам нужно что-то подобное, чтобы действительно получить намеченное поведение:

try:
    if x:
        return update(1)
    else:
        return update(2)
except:
    raise
else:
    notifyUpdated()

Во-вторых, поскольку блоки try обычно указывают на то, что вы выполняете какую-то обработку исключений, а вы нет, вы просто используете их для удобства. Так что эта конструкция будет смущать людей.

Например, я не думаю, что кто-либо из первых двух человек (по крайней мере, один из которых удалил свой ответ), чтобы ответить на ваш вопрос, понял, что вы действительно пытались сделать. Запутывающий код плох, независимо от того, насколько удобным и умным он кажется.

11
Omnifarious 16 Авг 2010 в 21:27

http://docs.python.org/library/contextlib.html:


from contextlib import closing
import urllib

with closing(urllib.urlopen('http://www.python.org')) as page:
    for line in page:
        print line

Так что вы можете создать аналогичную функцию и использовать ее

0
akonsu 16 Авг 2010 в 21:15

Я думаю, что декоратор - лучшая идея

def notifyupdateddecorator(f):
    def inner(*args, **kw):
        retval = f(*args, **kw)
        notifyUpdated()
        return retval
    return inner

@notifyupdateddecorator
def f(x):
    if x:
        return update(1)
    else:
        return update(2)

@notifyupdateddecorator
def g(x):
    return update(1 if x else 2)
3
John La Rooy 16 Авг 2010 в 22:45

Я думаю, что это вызывает проблемы. Что происходит позже, когда вы меняете свой код на следующий?

try:
    if x:
        return update(1)
    elif y:
        return update(2)
    else:
        return noUpdateHere()
finally:
    notifyUpdated() # even if noUpdateHere()!

В лучшем случае это камень преткновения для большинства читателей вашего кода (возможно, даже для вас через шесть месяцев), поскольку он использует try/finally для целей, которые отличаются от шаблонов обычного использования. И печатание это экономит минимально, так или иначе.

3
P Daddy 16 Авг 2010 в 21:26

Я думаю, вы имеете в виду, что вы хотите использовать try / finally в качестве альтернативы этому:

if x:
    result = update(1)
else:
    result = update(2)
notifyUpdated()
return result

Я думаю, это вопрос стиля. Для меня я хотел бы зарезервировать try для обработки исключительных условных. Я не буду использовать это как заявление управления потоком.

3
Wai Yip Tung 16 Авг 2010 в 21:21

Я бы не использовал try / finally для потока, который не включает исключения. Это слишком сложно для собственного блага.

Это лучше:

if x:
    ret = update(1)
else:
    ret = update(2)
notifyUpdated()
return ret
11
Ned Batchelder 16 Авг 2010 в 21:22