一枚python菜鸟刚开始看源码,发现了不懂的于是研究了下。
要理解python的装饰器,我们首先必须明白在Python中函数也是被视为对象。这一点很重要。理解python中的装饰器。
装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
看完上述文章就会明白,装饰器是个什么东西。
接下来发现网上有人提出了这个问题。
上代码:
def deco(func):
print ("before myfunc() called.")
func()
print ("after myfunc() called.")
return func
@deco
def myfunc():
print ("myfunc() called.")
myfunc()
myfunc()
他没有使用包装函数进行的实验,发现一个无法理解的问题。
运行结果:
before myfunc() called.
myfunc() called.
after myfunc() called.
myfunc() called.
myfunc() called.
这是为何?
首先,把两行myfunc()
删除掉,发现程序运行结果是:
before myfunc() called.
myfunc() called.
after myfunc() called.
我们知道,在上述实验中:
@deco
def myfunc():
print ("myfunc() called.")
可以看成等价于这样的操作
myfunc = deco(myfunc)
myfunc()
按照正常的写法,deco()函数应该这样写:
def deco(func):
def wapper():
print ("before myfunc() called.")
func()
print ("after myfunc() called.")
return func
return wapper
这样子,在执行myfunc=deco(myfunc)
的时候并不会执行wapper()
,结果就成了myfunc=wapper()
,这时候并没有什么执行,然后再调用myfunc()
,这时候执行wapper()里面的东西。正常执行:
before myfunc() called.
myfunc() called.
after myfunc() called.
before myfunc() called.
myfunc() called.
after myfunc() called.
没有包装函数的时候则不同,调用myfunc=deco(myfunc)
的时候直接执行了本来应该在wapper()
里面的代码,这时候已经输出三行信息,更要命的是,后面的return func
只是return了原来的func,并没有改变func,还是原来的配方,还是熟悉的味道。所以这时候再调用myfunc()
的时候就是调用原来的myfunc()
所以print了一行信息。
这同时也印证了第一个例子并没有改变myfunc()函数,所以输出的是那样的信息。