1

http://pythonprogramming.jottit.com/functional_programming有一个教程,它给出了一个如何使用高阶函数返回函数的示例:

def trace(f):
    f.indent = 0
    def g(x):
        print '|  ' * f.indent + '|--', f.__name__, x
        f.indent += 1
        value = f(x)
        print '|  ' * f.indent + '|--', 'return', repr(value)
        f.indent -= 1
        return value
    return g

def memoize(f):
    cache = {}
    def g(x):
        if x not in cache:
            cache[x] = f(x)
        return cache[x]
    return g

但我不明白它是如何在语句的同一个变量上分配两个函数的:

fib = trace(fib)
fib = memoize(fib)
print fib(4)

trace 和 memoize 似乎都对最后一次通话有影响。这是为什么?

4

3 回答 3

3

你写的很相似

fib2 = memoize(trace(fib))
print fib2(4)

因为您fib在调用 后更改了变量指向的函数trace,所以memoize应用于跟踪版本(然后fib再次“覆盖”)。

如果你想分别有一个跟踪版本和一个记忆版本,你需要将它们的结果分配给不同的变量,例如:

fib_trace = trace(fib)
fib_memo = memoize(fib)
print fib_trace(4), fib_memo(4)
于 2012-04-14T04:24:24.090 回答
2

这与以下没有什么不同:

a = a + 2
a = a + 5
print a

正如awill 增加 7 一样,fib将同时应用两个装饰器。

于 2012-04-14T04:17:22.067 回答
2

两者都trace()创建memoize()一个新的函数对象并将其返回给您。

在每种情况下,新函数对象都会“包装”旧函数对象,因此原始函数不会丢失。

使用我惊人的 ASCII 艺术技巧,这是一个图表:

f(x)   # this is your original function

trace(f(x))   # trace "wraps" it and returns a wrapped object

memoize(trace(f(x)))   # memoize "wraps" it and returns a new wrapped function object

我们从绑定到 name 的函数对象开始fib

然后我们调用trace(fib)which 创建一个新的函数对象。当它第一次被创建时,它的名字是,g但是我们将它绑定到名字fib上。尝试打印fib.__name__

然后我们调用memoize(fib)which 创建一个新的函数对象。同样,它首先使用名称创建,g但随后绑定到名称fib

请记住,在 Python 中,一切都是对象,对象可以没有名称、一个名称或多个名称而存在。在这种情况下,我们不断重复使用名称fib,但我们不断将其与不同的函数对象重新绑定。

于 2012-04-14T04:23:43.647 回答