装饰器
装饰器 decorator
在不改变原有函数代码,且保持原函数调用方法不变的情况下,给原函数增加新的功能(或者给类增加属性和方法)
装饰器定义与原型
- 核心思想
- 用一个函数(或者类)去装饰一个旧函数(或者类),造出一个新函数(或者新类)
- 语法规则
- 在原有的函数上加上@符号,装饰器会把下面的函数当做参数传递到装饰器中,@符又被称为语法糖
- 应用场景
- 引入日志,函数执行时间的统计,执行函数前的准备工作,执行函数后的处理工作,权限校验,缓存等场景中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| def outer(f): def inner(): print('这是inner函数的语句1') f() print('这是inner函数的语句2')
return inner
def demo(): print('这是demo函数的语句')
obj = outer(demo) obj()
print()
@outer def demo2(): print('这是使用装饰器的demo')
demo2()
|
统计函数执行时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import time
def cal_time(f): def inner(): time1 = time.perf_counter() f() time2 = time.perf_counter() elapsed = time2 - time1 print(f'函数运行了{elapsed}s') return elapsed
return inner
@cal_time def func(): for i in range(5): time.sleep(0.1) print('func运行结束')
func()
|
@wraps
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import time
def cal_time(f): @wraps(f) def inner(): time1 = time.perf_counter() f() time2 = time.perf_counter() print(f'函数运行了{time2 - time1}s')
return inner
@cal_time def func(): for i in range(5): time.sleep(0.1) print('func运行结束')
print(func) print(func.__name__)
|
装饰器的嵌套
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
def outer1(func): def inner1(): print('装饰器1————1') func() print('装饰器1————2')
return inner1
def outer2(func): def inner2(): print('装饰器2————3') func() print('装饰器2————4')
return inner2
@outer2 @outer1 def demo(): print('这是demo函数————5')
demo()
|
装饰带有参数的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| def outer(func): def inner(name): print('关于谁最美丽这件事') func(name)
return inner
@outer def love(name): print(f'{name}女士最美丽')
love('duandaun')
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import time
def cal_time(f): def inner(li): t1 = time.perf_counter() f(li) t2 = time.perf_counter() print(f'函数{f}执行了{t2-t1}s') return inner
@cal_time def sort_fun(li): for i in range(len(li)-1): for j in range(len(li)-1-i): if li[j] > li[j+1]: li[j],li[j+1] = li[j+1],li[j] return li
li = [5,4,3,2,1] sort_fun(li) print(li)
|
装饰带有多参数的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| def outer(func): def inner(who, name, *args, **kwargs): print(f'{name}回来啦') func(who, name, *args, **kwargs)
return inner
@outer def date(who, name, *args, **kwargs): print(f'{who}今天和{name}出门约会啦') print(f'我们吃了{args[0]}') print(f'还一起看了电影{kwargs}')
date('huanghuang', 'duandaun', '烤肉', movie='笨小孩')
|
带有参数的装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| def extend_m(var): def outer(func): def inner1(name): print(f'今天和{name}一起吃烤肉') func(name)
def inner2(name): print(f'今天和{name}一起吃火锅') func(name)
if var == '烤肉': return inner1 else: return inner2
return outer
@extend_m('烤肉') def date(name): print(f'和{name}约会啦,很开心!')
date('duanduan')
|
类装饰器修饰函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| class Outer():
def __call__(self, func): self.func = func return self.inner
def inner(self, who): print(f'和{who}一起看电影啦') self.func(who) print('约会吃烤肉啦哇')
@Outer() def date(who): print(f'今天和{who}约会啦')
date('duanduan')
class Outer: def __init__(self,func): self.func = func
def __call__(self,*args, **kwargs): print("今天出门啦") result = self.func(*args, **kwargs) print("今天结束啦") return result
@Outer def date(who): print(f"今天和{who}出门约会啦") print("出门看电影、吃烤肉啦") return success
print(date("duanduan"))
|
带有参数的类装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Outer: def __init__(self, name): self.name = name
def __call__(self,func): def inner(*args, **kwargs): print("今天出门啦") print(f"和{self.name}出门约会啦") result = func(*args, **kwargs) print("今天结束啦") return result return inner
@Outer("duanduan") def date(place:str): print(f"今天去{place}") print("出门看电影、吃烤肉啦") return success
print(date("北京"))
|
用类方法装饰函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Outer(): def newinner(func): Outer.func = func return Outer.inner
def inner(who): print(f'和{who}一起看电影啦') Outer.func(who) print(f'约会吃烤肉啦哇')
@Outer.newinner def date(who): print(f'今天和{who}约会啦')
date('duanduan')
|
使用函数装饰器装饰类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| def extend_c(cls): def func2(): print('在装饰器中扩展的新方法func2')
cls.func2 = func2 cls.name = '在装饰器中追加的新属性'
return cls
@extend_c class Demo(): def func(): print('Demo类中的func方法')
Demo.func() Demo.func2() print(Demo.name)
|
使用类装饰器装饰类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class Extend_c(): def __call__(self, cls): self.cls = cls return self.newfunc
def newfunc(self): self.cls.name = '在类装饰器中追加的新属性' self.cls.func2 = self.func2 return self.cls()
def func2(self): print('在类装饰器中追加的新方法 func2')
@Extend_c() class Demo(): def func(self): print('Demo类中的一个普通的方法')
obj = Demo() obj.func() obj.func2() print(obj.name) print(obj)
|
更新: 2024-05-16 12:24:07
原文: https://www.yuque.com/zacharyblock/cx2om6/fas3gy4akb8thh3c
Author:
Zachary Block
Permalink:
http://blockzachary.cn/blog/2025075349/
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE