18函数----装饰器(decorator)
Python允许使用装饰器对函数进行装饰,装饰器可以帮助函数实现一些通用的功能,在函数调用前运行些预备代码或函数调用后执行清理工作。如:插入日志、检测性能(计时)、事务处理、缓存、权限校验等。这样编写函数时就可以专注于功能的实现,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。
定义:装饰器本质就是函数,功能是在不更改原函数的代码前提下给函数增加新的功能。包装后返回一个装饰后的函数对象,该函数对象将更新原函数对象,程序将不再能访问原始函数对象。
装饰器的基础知识:=高阶函数+函数嵌套+闭包
原则:1不修改被修饰函数的源代码 2不修改被修饰函数的调用方式,在两者的前提上扩展其功能
例子1:
# 计算时间 import time def deco(func): def wrapper(*args, **kwargs):#接收任意参数 start_time = time.time() res = func(*args, **kwargs)#这里有括号,运行了func函数 end_time = time.time() spend_time = end_time - start_time print('运行时间:', spend_time) return res return wrapper @deco # foo=deco(foo) def foo(): time.sleep(1) print('hello cc') foo()
例子2:
# 验证授权 user_list = [{'username':'cc','password':123},{'username':'dd','password':111}] def auth(func): def wrapper(*args, **kwargs): name = input('name>>>:') pwd = int(input('pwd>>>:')) for i in user_list: if i['username'] == name and i['password'] == pwd: res = func(*args, **kwargs) return res return wrapper @auth def index(): print('index....') @auth def shopping(): print('shoppiing....') index() shopping()
例子3.1:带参装饰器(一)
# form functools import wraps提供了装饰器@wrap来保留原函数的属性 from functools import wraps user_list = [{'username':'cc','password':123},{'username':'dd','password':111}] def deco(type='a'):#type='a'默认参数 def auth(func): @wraps(func)#保留原函数的属性 def wrapper(*args, **kwargs): if type == 'a': print('这是参数aaaaaa') else: print('这是参数bbbbbb') name = input('name>>>:') pwd = int(input('pwd>>>:')) for i in user_list: if i['username'] == name and i['password'] == pwd: res = func(*args, **kwargs) return res return wrapper return auth @deco() # @deco(type='a')=====>@auth,但是这时候带了参数type='a' def index(): print('index....') @deco(type='kkkk') def shopping(): '''kkkkkkkkkkkkkkkkkk''' print('shoppiing....') index() shopping() print(shopping.__doc__)#装饰器@wrap来保留原函数的属性
例子3.2 带参装饰器(二)flask_web开发实战101页
def permission_required(permission): def decorator(f): @wraps(f) #@wrap来保留原函数的属性 def decorated_function(*args, **kwargs): if not current_user.can(permission): abort(403) #服务器拒绝了你的地址请求 return f(*args, **kwargs) return decorated_function return decorator def admin_required(f): return permission_required(Permission.ADMINISTER)(f) #下面是使用 @auth.route('/admin') @login_required @admin_required def for_admin(): return 'for admin' @auth.route('/moderator') @login_required @permission_required(Permission.MODERATE_COMMENTS) def for_moderator(): return 'for maderator'
例3.3 模拟session
# 模拟session from functools import wraps #装饰器@wrap来保留原函数的属性 userlist = [{'username':'cc', 'pwd':'123'}, {'username':'dd', 'pwd':'234'}, {'usernmae':'ee', 'pwd':'111'}] current_dit = {'username':None, 'login':False} #记录用户登录状态 def auth(func): @wraps(func) def wrapper(*args, **kwargs): if current_dit['username'] and current_dit['login']: return func(*args, **kwargs) name = input('please input your name:') pwd = input('please input pwd:') for user in userlist: if name==user['username'] and pwd==user['pwd']: current_dit['username'] = name current_dit['login'] = True return func(*args, **kwargs) else: print('name or pwd wrong') return wrapper @auth def index(): """dddd""" print('index...') @auth def shopping(): print('shoping....') index() shopping()
例子4:叠加多个装饰器
# 装饰器的加载顺序是从内到外的,从靠近函数的装饰器开始从内往外加载。 # 加载顺序:outer函数的调用顺序:自下而上 # 执行顺序:wrapper的执行顺序,自上而下 def outer1(func): print('加载了Outer1..') def wrapper1(*args, **kwargs): print('执行了wrapper1...') res = func(*args, **kwargs) return res return wrapper1 def outer2(func): print('加载了Outer2..') def wrapper2(*args, **kwargs): print('执行了wrapper2...') res = func(*args, **kwargs) return res return wrapper2 def outer3(func): print('加载了Outer3..') def wrapper3(*args, **kwargs): print('执行了wrapper3...') res = func(*args, **kwargs) return res return wrapper3 @outer1 @outer2 @outer3 def index(): print('from index.....') #====>index = outer1(outer2(outer3(index))) print('========') index() #结果: # 加载了Outer3.. # 加载了Outer2.. # 加载了Outer1.. # ======== # 执行了wrapper1... # 执行了wrapper2... # 执行了wrapper3... # from index.....
分类:
01Python学习
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
2020-04-03 02python基础----控制流程