7-35. Trace_Tool
目次
これまでに作成したデコレータ
- DEBUGGING TOOL
- countcall
- trace <- New!!
- PERFORMANCE TOOL
- memo
- EXPRESSION TOOL
- n_ary
Trace Tool
関数の実行のされ方がVisualizeされるデコレータ。
--> fib(6) --> fib(5) --> 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 --> 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(5) == 8 --> 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 <-- fib(6) == 13
# --------------- # User Instructions # # Modify the function, trace, so that when it is used # as a decorator it gives a trace as shown in the previous # video. You can test your function by applying the decorator # to the provided fibonnaci function. # # Note: Running this in the browser's IDE will not display # the indentations. 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: result = f(*args) #->関数はここで呼ばれる。再帰なので末尾に到着するまでreturnはなし。 print ('%s<-- %s == %s' % ((trace.level-1)*indent, signature, result)) finally: trace.level -= 1 return result 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(6) #running this in the browser's IDE will not display the indentations!
trace.level += 1
しているが、f(*args)
にてエラーになった際に元の位置に戻れるようにTry-Finallyにしている。