是否可以在 Python 中将两个高阶函数的返回值分配给同一个变量?[查看详情]



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)

跟踪和记忆似乎都对最后一次调用有影响。为什么?

你写的非常类似于

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

因为您在调用 trace 后更改了变量fib指向哪个函数,因此memoize应用于跟踪版本(然后再次"覆盖"fib)。

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

fib_trace = trace(fib)
fib_memo = memoize(fib)
print fib_trace(4), fib_memo(4)

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

我们从一个绑定到名称 fib 的函数对象开始。

然后我们调用 trace(fib) 创建一个新的函数对象。 首次创建时,它的名称是g,但随后我们将其绑定到名称 fib . 尝试打印fib.__name__

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

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

它与:

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

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

最新更新