【问题标题】:Memoization and Function Tracking记忆和功能跟踪
【发布时间】:2020-02-03 21:46:36
【问题描述】:

我正在尝试跟踪一个函数运行了多少次,并使用 memoization 来避免不必要地运行该函数。我不知道为什么,但似乎 memoization 为大多数值存储了两个相同的值。

def track(f):
  def wrapper(arg):
    wrapper.count += 1
    print(arg)
    return f(arg)
  wrapper.count = 0
  return wrapper

def memoize(f):
    memo = {}
    def wrapper(arg):
        if arg not in memo:            
            memo[arg] = f(arg)
        return memo[arg]
    return wrapper

@track
@memoize
def fib(n):
  return n if n in (0,1) else fib(n-1) + fib(n-2)

print('Result:', fib(10), '\nCount:', fib.count)

结果应该是这样的

10
9
8
7
6
5
4
3
2
1
0
Result: 55
Count: 11

由于某种原因,它会为小于 9 的所有内容释放双倍。Count 实际上返回 19。非常感谢任何帮助。

【问题讨论】:

  • 快速回答是你的装饰器执行了两次,因为你的函数是递归的。否则,我正在寻找答案以帮助解决您的问题。
  • 您正在跟踪memoize 函数。 memoize 调用了 19 次。

标签: python tracking memoization


【解决方案1】:

您需要将memoize 移动到track

def track(f):
  @memoize
  def wrapper(arg):
    wrapper.count += 1
    print(arg, end=' ')
    return f(arg)
  wrapper.count = 0
  return wrapper

def memoize(f):
    memo = {}
    def wrapper(arg):
        if arg not in memo:            
            memo[arg] = f(arg)
        return memo[arg]
    return wrapper

@track
def fib(n):
    return n if n in (0,1) else fib(n-1) + fib(n-2)

print('Result:', fib(10), '\nCount:', fib.count)
10 9 8 7 6 5 4 3 2 1 0 Result: 55 
Count: 11

通过向track 添加额外的参数,您可以控制是否要使用memoize 装饰器。在这种情况下,您应该使用 functools.wraps

from functools import wraps

def track(is_memoized):
  def dec(f):
    def wrapper(arg):
      wrapper.count += 1
      print(arg, end=' ')
      return f(arg)
    wrapper.count = 0
    if is_memoized:
      wrapper = memoize(wrapper)
    return wrapper
  return dec

def memoize(f):
    memo = {}
    @wraps(f)
    def wrapper(arg):
        if arg not in memo:            
            memo[arg] = f(arg)
        return memo[arg]
    return wrapper


@track(is_memoized=True)
def fib(n):
    return n if n in (0,1) else fib(n-1) + fib(n-2)

print('Result:', fib(10), '\nCount:', fib.count)
10 9 8 7 6 5 4 3 2 1 0 Result: 55 
Count: 11

@track(is_memoized=False)
def fib(n):
    return n if n in (0,1) else fib(n-1) + fib(n-2)

print('Result:', fib(5), '\nCount:', fib.count)
5 4 3 2 1 0 1 2 1 0 3 2 1 0 1 Result: 5 
Count: 15

【讨论】:

  • 完美!我真的不知道我怎么没想到。谢谢!
猜你喜欢
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-09
  • 1970-01-01
  • 2011-01-24
  • 2018-05-02
  • 2015-08-03
相关资源
最近更新 更多