【问题标题】:python try/finally for flow controlpython try/finally 用于流控制
【发布时间】:2010-08-16 21:08:18
【问题描述】:

我确信这个概念之前已经提出过,但我找不到一个好的、简单的答案。使用 try/finally 是处理具有多个返回的函数的坏方法吗?例如我有

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

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

【问题讨论】:

    标签: python control-flow try-catch-finally


    【解决方案1】:

    我不会推荐它。首先是因为notifyUpdated() 将被调用,即使任一分支中的代码抛出异常。您需要这样的东西才能真正获得预期的行为:

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

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

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

    【讨论】:

    • 关于它的好点是如此令人困惑,以至于前两个答案错过了标记。
    【解决方案2】:

    对于不涉及异常的流程,我不会使用 try/finally。它本身就太棘手了。

    这样更好:

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

    【讨论】:

      【解决方案3】:

      我认为你的意思是你想使用 try/finally 作为替代:

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

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

      【讨论】:

      • 虽然我猜这是风格问题,但我不认为这意味着这个问题没有是或否的答案。出于你所说的原因,我会明确地说“不”,因为它更令人困惑。
      • 我同意。我应该采取更强硬的立场。
      【解决方案4】:

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

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

      对于大多数阅读您的代码的读者来说,充其量是一个绊脚石(可能在六个月内甚至是您),因为它使用try/finally 的目的与正常使用模式不同。无论如何,它节省的打字量很少。

      【讨论】:

      • 我错过了那个绊脚石。这种情况在原始版本中已经以隐藏形式存在,因为如果 update(1)update(2) 抛出异常,也可能意味着不应调用 notifyUpdated()
      【解决方案5】:

      我认为装饰器在这里是一个更好的主意

      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】:

      来自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
      
      

      这样你就可以创建一个类似的函数并使用它

      【讨论】:

      • 并没有真正解决 OP 问题。
      • with stmt 是确保关闭时清理的合法方式
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-24
      • 2018-03-19
      • 2011-11-05
      • 2014-02-13
      • 2015-01-22
      • 2011-08-27
      • 2018-02-24
      相关资源
      最近更新 更多