我有一个简单的装饰器,输出把我搞糊涂了。
def deco(func):
def kdeco():
print("before myfunc() called.")
func()
print(" after myfunc() called.")
return kdeco
@deco
def myfunc():
print(" myfunc() called.")
myfunc()
before myfunc() called.
myfunc( deco(myfunc)()) called.
after myfunc() called.
deco(myfunc)()
before myfunc() called.
before myfunc() called.
myfunc() called.
after myfunc() called.
after myfunc() called.我知道myfunc()的输出,但是deco(myfunc)()的输出把我搞糊涂了,在下面的代码中,deco(myfunc)()的输出不能是它们中的任何一个吗?
状态一:
before myfunc() called.
before myfunc() called.
myfunc() called.
myfunc() called.
after myfunc() called.
after myfunc() called.状态二:
before myfunc() called.
myfunc( deco(myfunc)()) called.
after myfunc() called.
before myfunc() called.
myfunc( deco(myfunc)()) called.
after myfunc() called.发布于 2013-01-16 08:26:49
装饰器实际上只是一个捷径,你可以手动完成一些事情。这段代码:
@deco
def myfunc():
print(" myfunc() called.")等同于:
def myfunc():
print(" myfunc() called.")
myfunc = deco(myfunc)为了讨论这一点,让我们假设原始版本仍然以original_myfunc的形式提供(即使在现实中它不是)。
所以,当你这样做的时候:
deco(myfunc)()你最终会说的是:
deco(deco(original_myfunc))()如果你追踪一下,就会明白为什么它会打印出你所期望的结果。但不管怎样,我们还是来做练习吧。
首先,调用deco(original_myfunc),它执行以下操作:
def kdeco():
print("before myfunc() called.")
original_myfunc()
print(" after myfunc() called.")返回kdeco
因此,这将返回一个打印“之前”的函数,调用original_myfunc,然后打印“之后”。
现在我们再次将deco(original_myfunc)传递给deco,它会这样做:
def kdeco():
print("before myfunc() called.")
deco(original_myfunc)()
print(" after myfunc() called.")
return kdeco因此,这将返回一个打印“之前”的函数,然后调用deco(original_myfunc)-which本身打印“之前”,调用original_myfunc,并打印“之后”-then打印“之后”。
这就是为什么你会得到你所做的输出。
发布于 2013-01-16 08:26:31
myfunc本身已经被您的装饰器包装好了。名称myfunc不再指向原始方法,它现在指向deco(myfunc)的返回值
>>> def deco(func):
... def kdeco():
... print("before myfunc() called.")
... func()
... print(" after myfunc() called.")
... return kdeco
...
>>> @deco
... def myfunc():
... print(" myfunc() called.")
...
>>> myfunc
<function kdeco at 0x10068cb18>这是因为@decorator语法与以下内容相同:
def myfunc():
# body of function
myfunc = deco(myfunc)因此,myfunc已经生成了before ..、.. called和after ..这几行代码。现在你再把它包起来。包装器打印before ..,调用包装的myfunc (本身已经包装),它依次打印before ..、.. called和after ..,然后包装器打印after ..。
在图表中:
call wrapped myfunc():
kdeco: "before .."
call original myfunc()
original myfunc: ".. called"
kdeco: "after .."
call deco(myfunc)():
kdeco: "before .."
call wrapped myfunc():
kdeco: "before .."
call original myfunc()
original myfunc: ".. called"
kdeco: "after .."
kdeco: "after .."发布于 2013-01-16 08:24:36
修饰后的函数只被调用一次,因此它不能声明被调用了两次。
https://stackoverflow.com/questions/14349426
复制相似问题