不必要的尝试 - 终于

时间:2016-05-07 07:20:26

标签: python exception-handling try-catch

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

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的任何意义。有人可以向我解释一下吗?

1 个答案:

答案 0 :(得分:0)

尝试使用此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块中的代码。

修改

在你的情况下没有必要,但这通常是一种很好的做法。

@ pahn的

编辑

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

VS

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