【问题标题】:Unnecessary try-finally不必要的try-finally
【发布时间】:2016-05-07 07:20:25
【问题描述】:

Design of Computer Program 在 Udacity 上的一个讲座要求实现一个装饰器来跟踪递归:

from functools import update_wrapper

def decorator(d):
    "Make function d a decorator: d wraps a function fn."
    def _d(fn):
        return update_wrapper(d(fn), fn)
    update_wrapper(_d, d)
    return _d

@decorator
def trace(f):
    indent = '   '
    def _f(*args):
        signature = '%s(%s)' % (f.__name__, ', '.join(map(repr, args)))
        print '%s--> %s' % (trace.level*indent, signature)
        trace.level += 1
        try:
            # your code here
            print '%s<-- %s == %s' % ((trace.level-1)*indent, signature, result)
        finally:
            # your code here
        return # your code here
    trace.level = 0
    return _f

@trace
def fib(n):
    if n == 0 or n == 1:
        return 1
    else:
        return fib(n-1) + fib(n-2)

fib(4)

我将代码填充到trace 函数中,它可以工作:

@decorator
def trace(f):
    indent = '   '
    def _f(*args):
        signature = '%s(%s)' % (f.__name__, ', '.join(map(repr, args)))
        print '%s--> %s' % (trace.level*indent, signature)
        trace.level += 1
        try:
            result = f(*args)
            print '%s<-- %s == %s' % ((trace.level-1)*indent, signature, result)
        finally:
            trace.level -= 1
        return result
    trace.level = 0
    return _f

输出:

--> fib(4)
   --> fib(3)
      --> fib(2)
         --> fib(1)
         <-- fib(1) == 1
         --> fib(0)
         <-- fib(0) == 1
      <-- fib(2) == 2
      --> fib(1)
      <-- fib(1) == 1
   <-- fib(3) == 3
   --> fib(2)
      --> fib(1)
      <-- fib(1) == 1
      --> fib(0)
      <-- fib(0) == 1
   <-- fib(2) == 2
<-- fib(4) == 5

但很快我发现trace 可以不用try-finally

@decorator
def trace(f):
    indent = '   '
    def _f(*args):
        signature = '%s(%s)' % (f.__name__, ', '.join(map(repr, args)))
        print '%s--> %s' % (trace.level*indent, signature)
        trace.level += 1
        result = f(*args)
        print '%s<-- %s == %s' % ((trace.level-1)*indent, signature, result)
        trace.level -= 1
        return result
    trace.level = 0
    return _f

输出完全相同。

在这种情况下,我看不到 try-finally 的任何意义。谁能给我解释一下?

【问题讨论】:

  • 尝试在 fib 方法中引发异常。

标签: python exception-handling try-catch


【解决方案1】:

试试这个fib 方法,看看有什么不同。

@trace
def fib(n):
    if n == 0 or n == 1:
        raise RuntimeError('Test')
    else:
        return fib(n-1) + fib(n-2)

"try-finally" 确保 finally 块中的代码在异常引起的堆栈展开期间仍然执行。

编辑

在您的情况下,不需要它,但通常这是一种很好的做法。

编辑@Rahn

try:
    result = f(*args)
    print '%s<-- %s == %s' % ((trace.level-1)*indent, signature, result)
finally:
    print '%s<-- %s == Exception' % ((trace.level-1)*indent, signature)
    trace.level -= 1

对比

result = f(*args)
print '%s<-- %s == %s' % ((trace.level-1)*indent, signature, result)
trace.level -= 1

【讨论】:

  • 您的fib 似乎在try-finally 内外都产生相同的输出
  • OP 似乎知道try..finally 的作用——他只是说他认为在这种情况下 使用该构造没有任何意义。坦率地说,我也没有。
  • @Rahn 视觉上,是的。
  • @TigerhawkT3:除非您正在编写通用代码(@trace 装饰器可能被设计用于处理任意数量的函数),即使您最初使用它,也可以在遇到异常时保持弹性案例不能触发异常,总是一个好主意。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-24
  • 2014-11-27
  • 2011-02-20
  • 2019-02-28
  • 2013-12-26
  • 2018-03-19
  • 2014-01-08
相关资源
最近更新 更多