python try / finally для управления потоком - PullRequest
5 голосов
/ 17 августа 2010

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


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

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

Ответы [ 6 ]

11 голосов
/ 17 августа 2010

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

Это лучше:

if x:
    ret = update(1)
else:
    ret = update(2)
notifyUpdated()
return ret
11 голосов
/ 17 августа 2010

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

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

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

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

3 голосов
/ 17 августа 2010

Я думаю, что здесь лучше использовать декоратор

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 голосов
/ 17 августа 2010

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

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

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

3 голосов
/ 17 августа 2010

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

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

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

0 голосов
/ 17 августа 2010

от 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

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

...