装饰器python
装饰器
"""
1、什么是装饰器
装饰器是一个用来为被装饰者添加功能的工具
被装饰者:函数
装饰器:可以用函数实现装饰器这种工具
2、为何要用装饰器
为了在不修改被装饰器对象源代码以及调用方式的前提下
为被装饰对象添加上新功能
开放封闭原则(OCP,Open Closed Principle)是所有面向对象原则的核心。软件设计本身所追求的目标就是封装变化、降低耦合,而开放封闭原则正是对这一目标的最直接体现。其他的设计原则,很多时候是为实现这一目标服务的,例如以Liskov替换原则实现最佳的、正确的继承层次,就能保证不会违反开放封闭原则。
核心思想:软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。
3、如何用装饰器
"""
# 被装饰对象
import time
def index(x):
print('welcome to index page %s' % x)
time.sleep(3)
index(111)
# # 方案一:修改了源代码
# import time
#
# def index(x):
# start = time.time()
# print('welcome to index page %s' % x)
# time.sleep(3)
# stop = time.time()
# print(stop - start)
#
# index(111)
# # 方案二:没有修改被装饰对象的源代码与调用方式,但是有代码冗余问题
# import time
#
# def index(x):
# print('welcome to index page %s' % x)
# time.sleep(3)
#
# start = time.time()
# index(111)
# stop = time.time()
# print(stop - start)
#
#
# start = time.time()
# index(111)
# stop = time.time()
# print(stop - start)
#
#
# start = time.time()
# index(111)
# stop = time.time()
# print(stop - start)
# # 方案三:wrapper函数需要外部传入参数
import time
def index(x):
print('welcome to index page %s' % x)
time.sleep(3)
def wrapper():
start = time.time()
index(111)
stop = time.time()
print(stop - start)
wrapper()
# # 方案四:调用方式改变了
# import time
#
# def index(x):
# print('welcome to index page %s' % x)
# time.sleep(3)
#
# def wrapper(func):
# start = time.time()
# func(111)
# stop = time.time()
# print(stop - start)
#
#
# wrapper(index)
# 方案五:闭包函数
# import time
#
#
# def index(x):
# print('welcome to index page %s' % x)
# time.sleep(3)
#
#
# # index(111)
#
# def outter(func):
# def wrapper(*args, **kwargs):
# start = time.time()
# func(*args, **kwargs)
# stop = time.time()
# print(stop - start)
#
# return wrapper
#
#
# index = outter(index) # index = wrapper的内存地址
# # print(f)
# index(111) # wrapper(111)
# 方案五:把wrapper伪装的跟被装饰对象一样
# import time
#
#
# def index(x):
# print('welcome to index page %s' % x)
# time.sleep(3)
# return 7777
#
#
# def outter(func): # func = 地址1
# def wrapper(*args, **kwargs):
# start = time.time()
# res = func(*args, **kwargs)
# stop = time.time()
# print(stop - start)
# return res
# return wrapper
#
#
# index = outter(index) # index = outter(地址1) # index -> 地址2
#
# res = index(111) # res = wrapper(111)
# print(res)
# 方案六:把wrapper伪装的跟被装饰对象一样,更进一步
import time
def index(x):
"""
这是index的帮助信息
"""
print('welcome to index page %s' % x)
time.sleep(3)
return 7777
def outter(func): # func = 地址1
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
stop = time.time()
print(stop - start)
return res
wrapper.__doc__ = index.__doc__
wrapper.__name__ = index.__name__
return wrapper
index = outter(index) # index = outter(地址1) # index -> 地址2
# help(index)
语法糖
'''
语法糖(Syntactic sugar):
计算机语言中特殊的某种语法
这种语法对语言的功能并没有影响
对于程序员有更好的易用性
能够增加程序的可读性
'''
# 为了将装饰对象和被装饰对象一模一样,同时简化代码
def outter(func): # func = 地址1
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
stop = time.time()
print(stop - start)
return res
wrapper.__doc__ = func.__doc__
wrapper.__name__ = func.__name__
return wrapper
def index(x):
"""
这是index的帮助信息
"""
print('welcome to python %s' % x)
time.sleep(3)
return 7777
# 语法糖
import time
from functools import wraps
def outter(func): # func = 地址1
@wraps
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
stop = time.time()
print(stop - start)
return res
# wrapper.__doc__ = func.__doc__ # 这个方法不好用,函数体内置方法有很多,需要引入语法糖
# wrapper.__name__ = func.__name__
return wrapper
@outter # 相当于 index = outter(index)
def index(x):
"""
这是index的帮助信息
"""
print('welcome to index page %s' % x)
time.sleep(3)
return 7777
叠加多个装饰器
# 在面对多个叠加装饰器,如何分析
def deco1(func1):
def wrapper1(*args,**kwargs):
print(">>>来自wrapper1")
res1 = func1(*args,**kwargs)
return res1
return wrapper1
def deco2(func2):
def wrapper2(*args,**kwargs):
print(">>>来自wrapper2")
res2 = func2(*args,**kwargs)
return res2
return wrapper2
def deco3(func3):
def wrapper3(*args,**kwargs):
print(">>>来自wrapper3")
res3 = func3(*args,**kwargs)
return res3
return wrapper3
@deco1
@deco2
@deco3 # 1
def index():
print('from index')
return 123
res = index()
print(res)
# 装饰器加载顺序由下而上 ***
# 执行顺序自上而下 ****
有参装饰器
'''什么时有参装饰器
当内部函数需要参数时,我们想到的时构成闭包函数,为其传入参数
所以我们将其称之为有参装饰器
'''
#
def deco(func):
def wrapper(*args,**kwargs):
inp_user = input("username>>>:").strip()
inp_pwd = input("password>>>:").strip()
if inp_user = 'wuxie' and inp_pwd == '123':
res = func(*args,**kwargs)
return res
else:
print("登录失败!!!")
return wrapper
@deco # 语法糖
def index():
print("index功能") # 为其源函数加上认证功能
'''
新需求:当输入不同的值时,获取不同地方保存的用户信息
'''
# 方案一
# 直接传参
def deco(func,x):
def wrapper(*args,**kwargs):
print(x)
res = func(*args,**kwargs):
return res
return wrapper
# 此时可以完成需要,但是不能使用语法糖,语法糖的原则是只给一个参数传参
# 方案二
# 闭包函数
def outter(x,y):
def deco(func):
def wrapper(*args,**kwargs):
print(x,y)
res = func(*args,**kwargs)
return res
return wrapper
return deco
# 在调用时候仍然可以使用语法糖
@outter(111,22) # 此时触发的是 outter函数执行结果,而outter的返回值是deco,相当于@deco实现传参,同时使用语法糖,
def index():
print('index')
index()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端