为什么我用这个装饰函数得到多个输出?

Why am I getting multiple outputs with this decorated function?

我最近从 C/C++ 搬到了 Python。难以理解闭包和装饰器。

这样声明函数(某在线博客以这段代码为例)

def outer(some_func):
    def inner():
        print "Before Foo"
        ret = some_func()
        return ret + 1

    return inner

def foo():
    return 1

当我运行下面的代码一次

foo = outer(foo)
foo()

我得到了预期的输出

Before Foo
2

但是,如果我 运行 它不止一次,我会得到奇怪的输出。我不明白发生了什么。

# Writing it down twice instead of running the same cell 
# twice on my IPython notebook to better explain things here
foo = outer(foo)
foo = outer(foo)    
foo()

输出结果如下

Before Foo
Before Foo
3

为什么我的输出是 3,为什么 "Before Foo" 打印了两次?

编辑:- 当我再次修饰函数时会发生什么? 运行 foo = outer(foo) 现在很清楚了。当我再次 运行 foo = outer(foo) 时会发生什么?

考虑一下 foofoo=outer(foo) 的每个语句中指的是什么。最初,您将 foo 定义为始终 returns 1 的函数。不过,一旦您调用 foo=outer(foo) ,它现在就有了一个新值。试着想象用 运行 该行之前的 foo 替换赋值右侧的 foo 。请记住,您在此处嵌套函数。

可以帮助您了解正在发生的事情的几种方法是

  1. 向函数的不同部分添加更多打印语句,以帮助理解调用的内容和调用时间。
  2. 除非有理由,否则不要重新分配给变量 foo。或许可以选择 foo1、foo2 等,这样您就可以回顾 foo 的先前迭代,更清楚地看到正在发生的合成。

您又在装饰被装饰函数了。 outer 接受一个函数和 return 的闭包,当然它本身就是一个函数。没有什么能阻止您将 returned 函数作为参数传递给以下调用,就像您在示例中所做的那样。

如果您更改代码以打印被调用的函数和 return 值,则更容易理解发生了什么:

def outer(some_func):
    def inner():
        print "Before inner, func: {0}".format(some_func)
        ret = some_func()
        print "After inner, return: {0}".format(ret + 1)
        return ret + 1

    return inner

def foo():
    return 1

foo = outer(foo)
foo = outer(foo)
foo()

输出:

Before inner, func: <function inner at 0x7f1924b516e0>
Before inner, func: <function foo at 0x7f1924b51668>
After inner, return: 2
After inner, return: 3

问题 hoebenkr,我不明白当您将变量 ret 分配给函数的参数时,您如何调用 函数。这是向函数声明变量的实际标准吗?它会在 python?

中立即运行