callable objectでデコレータを作成

以前にcallble objectを使うことでもデコレータが作れるということを試してみた。
今度はcallable objectを使ってできることを考えてみる。

再帰呼び出しの内容を把握しやすいように表示するtraceを作ってみた

対象

  • デコレータの使い方を知っている
  • callable objectを知っている
  • 再帰が怖い

callble objectだと何が違うのか

objectなので状態が持てる。

コード

class Tracer(object):
    def __init__(self, delta=2):
        self.n = 0
        self.delta = delta

    def __call__(self, fn):
        def _fn(*args, **kw):
            space = " "*self.n
            print("%s%s: args = %s ,  kw = %s" % (space, fn, args, kw))
            self.n += self.delta
            result = fn(*args, **kw)
            self.n -= self.delta
            print("%s%s: result = %s" % (space, fn, result))
            return result
        return _fn

@Tracer()
def f(n):
    return 1 if n <= 1 else n * f(n-1)

print f(10)

結果

$ python /home/nao/sandbox/python/callable-decolator.py

<function f at 0xb38320>: args = (10,) ,  kw = {}
  <function f at 0xb38320>: args = (9,) ,  kw = {}
    <function f at 0xb38320>: args = (8,) ,  kw = {}
      <function f at 0xb38320>: args = (7,) ,  kw = {}
        <function f at 0xb38320>: args = (6,) ,  kw = {}
          <function f at 0xb38320>: args = (5,) ,  kw = {}
            <function f at 0xb38320>: args = (4,) ,  kw = {}
              <function f at 0xb38320>: args = (3,) ,  kw = {}
                <function f at 0xb38320>: args = (2,) ,  kw = {}
                  <function f at 0xb38320>: args = (1,) ,  kw = {}
                  <function f at 0xb38320>: result = 1
                <function f at 0xb38320>: result = 2
              <function f at 0xb38320>: result = 6
            <function f at 0xb38320>: result = 24
          <function f at 0xb38320>: result = 120
        <function f at 0xb38320>: result = 720
      <function f at 0xb38320>: result = 5040
    <function f at 0xb38320>: result = 40320
  <function f at 0xb38320>: result = 362880
<function f at 0xb38320>: result = 3628800
3628800

もう再帰なんて怖くない><