0

Python でジェネレーター、デコレーター、辞書を使用する能力を試す問題を作成しました。

ただし、この演習を自分で解決することはできず、解決できるかどうか疑問に思っていました。

ジェネレーターをラップするデコレーター関数を使用して、関数出力を辞書の形でキャッシュすることは可能ですか?

演習は次のとおりです。

関数呼び出しの結果をキャッシュするデコレーターを作成します。関数オブジェクトの属性のディクショナリに arg:result のペアを格納します。ジェネレーター関数を使用してこれらの結果を生成する フィボナッチ関数でコードをテストします。

私は次のようにそれを実装しようとしました:

def cachefunc(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return {func.__name__ + '(' + str(list(args))[1:-1] + ')' : str(result)}
    wrapper.__name__ = func.__name__
    wrapper.__doc__ = func.__doc__
    return wrapper

@cachefunc
def fibonacci(n):
    assert n >= 0
    if n < 2:
        return n
    else:
        return (fibonacci(n-1) + fibonacci(n-2))
def allfib():
    n = 0
    while True:
        yield fibonacci(n)
        n += 1

result = []
generator = allfib()
while len(result) < 10:
    x = next(generator)
    result.append(x)
print result

ただし、次のエラーが表示されます。

python dg.py
Traceback (most recent call last):
  File "dg.py", line 32, in <module>
    x = next(generator)
  File "dg.py", line 26, in allfib
    yield fibonacci(n)
  File "dg.py", line 10, in wrapper
    result = func(*args, **kwargs)
  File "dg.py", line 22, in fibonacci
    return (fibonacci(n-1) + fibonacci(n-2))
TypeError: unsupported operand type(s) for +: 'dict' and 'dict'

このような質問に対する別の解決策を知っている人はいますか?

4

1 に答える 1

1

あなたの特定のエラー

エラーは次のとおりです。

return {func.__name__ + '(' + str(list(args))[1:-1] + ')' : str(result)}

結果を返したいときに辞書を返していると思います。キャッシュ関数内で実際にキャッシュを行っている場所がよくわかりません。

一般的なコメント

このキャッシュのパターンは、一般にメモ化とも呼ばれます。

このhttp://avinashv.net/2008/04/python-decorators-syntactic-sugar/を試してください。フィボナッチに関する部分までスクロールします。次のコードがそこにあります。

class memoize:
  def __init__(self, function):
    self.function = function
    self.func_name = function.__name__
    self.memoized = {}

  def __call__(self, *args):
    try:
      print "Using Memo Solution for " + self.func_name + " on " + str(args)
      return self.memoized[args]
    except KeyError:
      print "Computing Solution Now for " + self.func_name + " on " + str(args)
      self.memoized[args] = self.function(*args)
    return self.memoized[args]

次に、次のようにします。

@memoize
def fibonacci(n):
  assert n >= 0
  if n < 2:
    return n
  else:
    return (fibonacci(n-1) + fibonacci(n-2))

完全なコード

メモ化は、例のジェネレーターで引き続き機能します。印刷ステートメントは、メモ化された結果がフェッチされていることを示していることに注意してください。

class memoize:
  def __init__(self, function):
    self.function = function
    self.func_name = function.__name__
    self.memoized = {}

  def __call__(self, *args):
    try:
      print "Using Memo Solution for " + self.func_name + " on " + str(args)
      return self.memoized[args]
    except KeyError:
      print "Computing Solution Now for " + self.func_name + " on " + str(args)
      self.memoized[args] = self.function(*args)
    return self.memoized[args]

@memoize
def fibonacci(n):
  assert n >= 0
  if n < 2:
    return n
  else:
    return (fibonacci(n-1) + fibonacci(n-2))

def allfib():
  n = 0
  while True:
    yield fibonacci(n)
    n += 1

result = []
generator = allfib()
while len(result) < 10:
  x = next(generator)
  result.append(x)
print result
于 2013-03-21T02:10:04.833 に答える