为什么我用这个装饰函数得到多个输出?
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) 时会发生什么?
考虑一下 foo
在 foo=outer(foo)
的每个语句中指的是什么。最初,您将 foo 定义为始终 returns 1 的函数。不过,一旦您调用 foo=outer(foo)
,它现在就有了一个新值。试着想象用 运行 该行之前的 foo 替换赋值右侧的 foo 。请记住,您在此处嵌套函数。
可以帮助您了解正在发生的事情的几种方法是
- 向函数的不同部分添加更多打印语句,以帮助理解调用的内容和调用时间。
- 除非有理由,否则不要重新分配给变量 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?
中立即运行
我最近从 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) 时会发生什么?
考虑一下 foo
在 foo=outer(foo)
的每个语句中指的是什么。最初,您将 foo 定义为始终 returns 1 的函数。不过,一旦您调用 foo=outer(foo)
,它现在就有了一个新值。试着想象用 运行 该行之前的 foo 替换赋值右侧的 foo 。请记住,您在此处嵌套函数。
可以帮助您了解正在发生的事情的几种方法是
- 向函数的不同部分添加更多打印语句,以帮助理解调用的内容和调用时间。
- 除非有理由,否则不要重新分配给变量 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?
中立即运行