2016-05-07 5 views
0

Ein Vortrag von Design of Computer Program auf Udacity bitten, einen Dekorateur zu implementieren Rekursion verfolgen:Unnötige try-finally

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) 

ich den Code in trace Funktion ausfüllen und es funktioniert:

@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 

Ausgang:

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

Aber bald finde ich heraus, dass trace könnte gehen ohne 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 

Mit genau dem gleichen Ausgang.

Ich sehe keinen Punkt von try-finally in diesem Fall. Kann mir das jemand erklären?

+0

versuchen, eine Ausnahme in der 'fib' Methode zu erhöhen. – totoro

Antwort

0

Versuchen Sie mit dieser fib Methode und sehen Sie den Unterschied.

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

„Try-finally“ stellt sicher, dass der Code im finally-Block noch während der Stapel Abwickeln verursacht durch eine Ausnahme ausgeführt wird.

bearbeiten

In Ihrem Fall ist es nicht notwendig, aber es ist in der Regel gute Praxis.

bearbeiten für @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 

gegen

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

Ihr 'fib' scheint die gleiche Ausgabe innerhalb oder außerhalb von' try-finally' zu erzeugen – Wentao

+0

Der OP scheint zu wissen, was "try..finally" tut - er sagte einfach, dass er keinen Sinn darin sieht, dieses Konstrukt zu verwenden _in diesem Fall_ . Ehrlich gesagt, ich auch nicht. – TigerhawkT3

+0

@Rahn Visuell, ja. – totoro

Verwandte Themen