代码之家  ›  专栏  ›  技术社区  ›  Falmarri

python try/finally用于流控制

  •  5
  • Falmarri  · 技术社区  · 14 年前

    我相信这个概念以前就有过,但我找不到一个好的、简单的答案。使用Try/Finally处理具有多个返回的函数是否是一种错误的方法?例如我有

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

    这似乎比在临时变量中存储update()命令并返回该命令要好。

    6 回复  |  直到 13 年前
        1
  •  11
  •   Omnifarious    14 年前

    我不推荐。首先因为 notifyUpdated() 即使分支中的代码引发异常,也将调用。您需要这样的东西才能真正获得预期的行为:

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

    其次,因为 try 块通常表示您正在进行某种异常处理,而您没有,只是为了方便而使用它们。所以这个结构会让人困惑。

    例如,我不认为前两个人(其中至少有一个人删除了他们的答案)中的任何一个回答了你的问题,意识到你真正想做的是什么。混淆代码是不好的,不管它看起来多么方便和聪明。

        2
  •  11
  •   Ned Batchelder    14 年前

    对于不涉及异常的流,我不会使用Try/Finally。这件事本身就太棘手了。

    这样比较好:

    if x:
        ret = update(1)
    else:
        ret = update(2)
    notifyUpdated()
    return ret
    
        3
  •  3
  •   Wai Yip Tung    14 年前

    我认为你的意思是,你想用“尝试/最终”作为替代方法:

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

    我想这是风格问题。对我来说,我喜欢预订 try 处理异常条件。我不会将它用作流控制语句。

        4
  •  3
  •   P Daddy    14 年前

    我认为这是自找麻烦。当您将代码更改为以下代码时,稍后会发生什么?

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

    充其量,对于大多数代码的读者来说,它是一个绊脚石(甚至可能是六个月后的您),因为它使用 try/finally 用于不同于正常使用模式的用途。无论如何,它保存的输入量是最小的。

        5
  •  3
  •   John La Rooy    14 年前

    我觉得这里最好有个装修工

    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)
    
        6
  •  0
  •   akonsu    14 年前

    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
    
    

    所以您可以创建一个类似的函数并使用它