装饰器 decorator
一、装饰器定义
在不改变原有函数代码,且保持原函数调用方法不变的情况下,给原函数增加新的功能(或者给类增加属性和方法) 核心思想:用一个函数(或者类)去装饰一个旧函数(或者类),造出一个新函数(或者新类) 应用场景:引入日志,函数执行时间的统计,执行函数前的准备工作,执行函数后的处理工作,权限校验,缓存等 语法规则:在原有的函数上加上 @符,装饰器会把下面的函数当作参数传递到装饰器中,@符又被成为 语法糖
1.装饰器原型(闭包)
def outer(f
):
def inner():
print('我是外函数中的内函数1')
f
()
print('我是外函数中的内函数2')
return inner
@outer
def old():
print('我是一个普通的函数')
old
()
2.装饰器的应用:统计函数的执行时间
import time
def runtime(f
):
def inner():
start
= time
.perf_counter
()
f
()
end
= time
.perf_counter
() - start
print(f
'函数的调用执行时间为:{end}')
return inner
@runtime
def func():
for i
in range(5):
print(i
,end
=" ")
time
.sleep
(1)
func
()
3.装饰器嵌套语法
def outer(func
):
def inner():
print('找到妹子,成功拿到微信。。。3')
func
()
print('约妹子,看一场午夜电影。。。4')
return inner
def kuozhan(f
):
def kzinner():
print('扩展1')
f
()
print('扩展2')
return kzinner
@kuozhan
@outer
def love():
print('跟妹子畅谈人生和理想。。。5')
love
()
''' 结果和过程的解析
1 3 5 4 2
1 先使用离得近的 outer装饰器 装饰love函数,返回了一个 inner函数
2 再使用上面的 kuozhan 装饰器,装饰 上一次返回的 inner 函数,又返回了 kzinner 函数
最后在调用love函数的时候是怎么执行的
love() == kzinner()
===> 1
===> inner()
===> 3
===> love() ===> 5
===> 4
===> 2
'''
4.对带有参数的函数进行装饰
def outer(func
):
def inner(var
):
print(f
'找到{var}妹子,成功拿到微信。。')
func
(var
)
print(f
'约{var}妹子,看一场午夜电影。。')
return inner
@outer
def love(name
):
print(f
'跟{name}妹子畅谈人生。。。')
love
('思思')
5.对多参数的函数进行装饰
def outer(func
):
def inner(who
,name
,*args
,**kwargs
):
print('约到妹子,聊微信。。。')
func
(who
,name
,*args
,**kwargs
)
print('天色一晚,怎么办?')
return inner
@outer
def love(who
,name
,*args
,**kwargs
):
print(f
'{who}跟{name}畅谈人生。。。')
print('完事去吃了好多美食',args
)
print('看了一场电影',kwargs
)
love
('三多','思思','火锅','辣条','7块钱的麻辣烫',mov
='唐山大地震')
'''
love() ==> inner()
love(...) ==> inner(...)
inner(...) ==> love(...)
'''
6.带有参数的装饰器
你会遇到带有参数的装饰器,例如Django框架中的 @login_required(login_url=’/accounts/login/’)
def kuozhan(var
):
def outer(func
):
def inner1():
print('妹子给了你微信')
func
()
def inner2():
print('妹子给介绍了个大妈')
func
()
if var
== 1:
return inner1
else:
return inner2
return outer
@kuozhan
(2)
def love():
print('谈谈人生。。。')
love
()
7.用类装饰器装饰函数
class Outer():
def __call__(self
,func
):
self
.func
= func
return self
.inner
def inner(self
,who
):
print('拿到妹子的微信。。。')
self
.func
(who
)
print('看一场午夜电影。。。')
@Outer
()
def love(who
):
print(f
'{who}和妹子谈谈人生和理想。。。')
love
('川哥')
print(love
)
8.用类方法装饰函数
class Outer():
def newinner(func
):
Outer
.func
= func
return Outer
.inner
def inner():
print('拿到妹子微信')
Outer
.func
()
print('看一场午夜电影')
@Outer
.newinner
def love():
print('和妹子谈谈人生喝喝茶。。。')
love
()
到目前为止以上所以形式的装饰器,包括 函数装饰器,类装饰器,类方法装饰器,都有一个共同特点:都是在给函数去进行装饰,增加功能。
用装饰器装饰类
还有一种装饰器,是专门装饰类的。也就是在类的定义的前面使用@装饰器这种语法 @装饰器 class Demo(): pass
装饰器给函数进行装饰,目的是不改变函数调用和代码的情况下给原函数增加了新的功能。
装饰器给类进行装饰,目的是不改变类的定义和调用的情况下给类增加新的成员(属性或方法)。
9.用函数装饰器装饰类
def kuozhan(cls
):
def func2():
print('我是在装饰器中追加的新方法,func2')
cls
.func2
= func2
cls
.name
= '我是在装饰器中追加的新属性 name'
return cls
@kuozhan
class Demo():
def func():
print('我是Demo类中定义的func方法')
Demo
.func
()
Demo
.func2
()
print(Demo
.name
)
10.使用类装饰器装饰类
class KuoZhan():
def __call__(self
, cls
):
self
.cls
= cls
return self
.newfunc
def newfunc(self
):
self
.cls
.name
= '我是在类装饰器中追加的新属性 name'
self
.cls
.func2
= self
.func2
return self
.cls
()
def func2(self
):
print('我是在类装饰器中追加的新方法 func2')
@KuoZhan
()
class Demo():
def func(self
):
print('我是Demo类中定义的func方法')
obj
= Demo
()
obj
.func
()
obj
.func2
()
print(obj
.name
)
print(obj
)