学习了闭包的概念之后,再来学习装饰器就简单很多。
装饰器就是闭包的一个应用
代码举例
def decorator(func):
def warapper(x):
a="2222222222222"
return func(x)#此处return的意义是执行完装饰器函数的内部要返回到原来执行的函数func()调用处执行。不能是return func有点像中断一样,中断执行完返回中断处继续执行以前的函数
return warapper #此处return的意义是要将包含a变量的函数返回出去。不然外界如何调用到a
@decorator#func=decorator(func),而decorator(func)返回的是warapper,所以func=warapper
def func(x):
b="11111111111111"
return "result"
a=func(1) #warapper(1)
但是装饰器在使用时分加载态和调用态
加载态
加载态是指当@decorator加到func()函数上面时,装饰器函数在被装饰函数定义好后立即执行。即func=decorator(func),而decorator(func)返回的是warapper,所以func=warapper。这是加载态也就是func函数还未被实例化调用时就已经产生的状态。
调用态
当a=func()时,开始调用态,此处a=func(1) 等于warapper(1),那么就会进入到warapper函数,(记住,此时不会再调用一次decorator函数了,因为已经在加载态完成了调用,并且返回了warapper给func函数,所以此时是直接进入到warapper函数),当执行完warapper之后,就是完成了装饰器的功能,那么就应该返回到a=func(1)处,即return func()。问题来了为什么不是return func呢,因为当我们要执行a=func(1)是想执行func(1)的调用,但是由于装饰器的存在,执行流程先跑到装饰器warapper函数中,后装饰器执行完了得回到刚才的执行处继续执行func(1)的调用,所以此处是return func(x),这相当于中断返回,返回后完成中断之前要做的操作。
拓展
装饰器能否修改被装饰参数的参数?答案是可以的,如下代码,在原来的参数基础上新增了一个key
def decorate(function):
def wrap_function(*args, **kwargs):
kwargs['str'] = 'Hello!' ##新增了一个key
return function(*args, **kwargs)
return wrap_function
@decorate
def print_message(*args, **kwargs):
print(kwargs['str'])
网友评论