2012-04-14 50 views
1

有一个在http://pythonprogramming.jottit.com/functional_programming一个教程,它给出了一个例子,如何使用高阶函数返回功能:是否有可能从两个高阶函数指定返回值Python中相同的变量[查看详细]

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) 

跟踪和记忆似乎对最后一次呼叫有影响。这是为什么?

+1

“既跟踪和memoize的似乎对最后的通话效果”他们都被叫了。还有其他问题吗? – 2012-04-14 04:09:53

回答

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 

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

则称trace(fib)这将创建一个新的函数对象。当它第一次创建时,其名称是g,但我们将它绑定到名称fib。尝试打印fib.__name__

则称memoize(fib)这将创建一个新的函数对象。它再次以名称g创建,但随后绑定到名称fib

记住,Python中一切都是对象,并且对象可以没有名字的存在,有一个名字,或者有许多名字。在这种情况下,我们继续使用名称fib,但我们不断使用不同的函数对象重新绑定它。

2

这是没有什么不同:

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

正如a将增加7,fib将有两个装饰应用了。

+0

对不起@Ignacio上面的比喻感觉不同于我的问题。在你的情况下,a被一个新值“覆盖”我没有更多的东西。也许我必须阅读装饰器。我认为这两个函数都会生成新的函数,而fib将在第二个任务上被覆盖。你能告诉我幕后发生了什么吗? – 2012-04-14 10:50:12

+0

'fib'被覆盖。他们对fib *用来包含的对象的引用仅仅是绒毛。 – 2012-04-14 14:00:09

+0

它如何执行这两项工作(追踪,记忆)呢? – 2012-04-14 18:47:57

3

你写的是非常相似的

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

,因为你已经改变了功能变量fib指向调用trace后,所以memoize应用于跟踪版本(然后fib是“重写”)。

如果要单独有一个跟踪版本和memoized版本,你需要分配的结果不同的变量,如:

fib_trace = trace(fib) 
fib_memo = memoize(fib) 
print fib_trace(4), fib_memo(4) 
相关问题