python基础之装饰器详解
一、前言
装饰器:本质就是函数,功能是为其他函数添加附加功能
原则:
- 1、不修改被修饰函数的源代码
- 2、不修改被修饰函数的调用方式
装饰器 = 高阶函数 + 函数嵌套 + 闭包
二、高阶函数
高阶函数定义:
- 1、函数接收的参数是一个函数
- 2、函数的返回值是一个函数名
- 3、满足上述条件任意一个,都可以称为高阶函数
test 函数是高阶函数,接受了一个foo 作为参数
import timedef foo(): time.sleep(3) print("sleep 3s") def test(func): start_time = time.time() func() stop_time = time.time() print("函数的运行时间是: %s" % (stop_time - start_time)) test(foo)
timer 是一个高阶函数,这个函数返回值是一个函数
import timedef foo(): time.sleep(3) print("sleep 3s") def timer(func): start_time = time.time() func() stop_time = time.time() print("执行时间{}".format(stop_time - start_time)) return funcfoo = timer(foo)foo()# 结果: 多运行了一次
三、函数嵌套
在函数里面定义函数,变量的作用域和生存周期不变。
def father(name): print("father name: %s" % name) def son(): print("son name: %s" % name) son()father("xu1") # 结果:# father name: xu1# son name: xu1
四、装饰器
实现一个计算函数执行时间的函数作为装饰器,用来计算被装饰函数的执行时间并打印
import time def timer(func): # 实现一个计算函数执行时间的函数作为装饰器,用来计算被装饰函数的执行时间并打出 def wrapper(): start_time = time.time() func() stop_time = time.time() print("运行时间: %s" % (stop_time - start_time)) return wrapper # def test(): # 不使用装饰器的同等实现# time.sleep(3)# print("test sleep 3s")## test = timer(test) # 返回的是 wrapper 的地址# test() # 执行的是 wrapper @timerdef test(): # 装饰器的实现 time.sleep(3) print("test sleep 3s") test() # 执行的是 wrapper# 结果:# test sleep 3s# 运行时间: 3.000915050506592
4.1 被装饰方法带返回值
import time def timer(func): def wrapper(): start_time = time.time() res = func() # 执行被装饰方法 stop_time = time.time() print("运行时间: %s" % (stop_time - start_time)) return res # 接受正在调用的方法的返回值,并返回 return wrapper @timerdef test(): time.sleep(3) print("test sleep 3s") return "test return ok" print(test()) # 执行的是 wrapper# 结果:# test sleep 3s# 运行时间: 3.0002923011779785# test return ok
4.2 被装饰方法带参数
import time def timer(func): """ *args:将被修饰方法传入的非关键字参数打包为元组 args **kwargs: 将被修饰方法传入的关键字参数打包为字典 kwargs """ def wrapper(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) # *args 拆解元组,按顺序传给被修饰函数; **kwargs:拆解字典 stop_time = time.time() print("运行时间: %s" % (stop_time - start_time)) return res return wrapper @timer # 给test 方法添加计算执行时间的装饰器def test(name, age): time.sleep(3) print("name = {}, age = {}".format(name, age)) return "test return ok" # 调用被装饰器装饰的方法print(test("xu", 100)) # 执行的是 wrapper# 结果:# name = xu, age = 100# 运行时间: 3.000420331954956# test return ok
4.3 验证功能装饰器
假如 index() 、home()、shopping_car() 三个方法都需要登录后才能访问(无法访问时里面不输入对应内容),正常情况下只需登录一次,后面访问其他方法就无需再次登录。
可以通过@auth_fun装饰器进行验证用户是否登录,如果没有就让用户输入账号密码,用户账号密码正确的记录当前登录的用户,其他方法无需再次登录。
# 用户列表user_list = [ {'name': 'xu1', 'passwd': '123'}, {'name': 'xu2', 'passwd': '123'}, {'name': 'xu3', 'passwd': '123'}, {'name': 'xu4', 'passwd': '123'},]# 当前登录的用户current_dic = {"username": None, "login": False} # 验证用户是否登录的装饰器# 如果用户没有登录,让用户输入账号密码,校验通过记录用户状态def auth_fun(func): def wrapper(*args, **kwargs): if current_dic["username"] and current_dic['login']: res = func(*args, **kwargs) return res username = input("请输入用户名:") pw = input("请输入密码:") for u in user_list: if u["name"] == username and u["passwd"] == pw: current_dic["username"] = username current_dic["login"] = True res = func(*args, **kwargs) return res else: print("用户没有注册!") return wrapper @auth_fundef index(): print("this is index") @auth_fundef home(): print("this is home page") @auth_fundef shopping_car(): print("this is shopping car") index() # 输入用户密码home() # index 已经登录,无需在输入shopping_car() # index 已经登录,无需在输入# 结果:# 请输入用户名:xu1# 请输入密码:123# this is index# this is home page# this is shopping car
4.4 验证功能装饰器――带参数
装饰器带参数,最简单的操作就是可以对被装饰的函数进行区别处理。
# 用户列表user_list = [ {'name': 'xu1', 'passwd': '123'}, {'name': 'xu2', 'passwd': '123'}, {'name': 'xu3', 'passwd': '123'}, {'name': 'xu4', 'passwd': '123'},]# 当前登录的用户current_dic = {"username": None, "login": False} """ 注意:带参数的装饰器会比没有带参数的装饰器多嵌套一层函数(多了auth) 调用方式是 @auth(auth_type="type1"), 返回 auth_fun, 也就是说 @auth(auth_type="type1")相当于 @auth_fun 但是 auth_fun 函数所在的嵌套作用域多了一个 auth_type 的变量"""def auth(auth_type="type1"): def auth_fun(func): def wrapper(*args, **kwargs): if auth_type == "type1": if current_dic["username"] and current_dic['login']: res = func(*args, **kwargs) return res username = input("请输入用户名:") pw = input("请输入密码:") for u in user_list: if u["name"] == username and u["passwd"] == pw: current_dic["username"] = username current_dic["login"] = True res = func(*args, **kwargs) return res else: print("用户没有注册!") elif auth_type == "type2": print("不用授权直接登录: type = {}".format(auth_type)) res = func(*args, **kwargs) return res else: print("其他type没有实现") return wrapper return auth_fun """ auth_fun = @auth(auth_type="type1") auth_fun 所在的嵌套与将有一个 auth_type 变量 然后通过 @auth()方法返回的对象注解 index,相当于 @auth_fun 注解index 方法,最后得到 wrapper 对象"""@auth(auth_type="type1")def index(): print("this is index") @auth(auth_type="type2")def home(): print("this is home page") @auth(auth_type="type3")def shopping_car(): print("this is shopping car") home() # 注意:auth_type="type2",这个方法无需登录可以直接执行index() # 注意:auth_type="type1",需要登录shopping_car() # 注意:auth_type="type3",没有做处理# 结果:# 不用授权直接登录: type = type2# this is home page# 请输入用户名:xu1# 请输入密码:123# this is index# 其他type没有实现
到此这篇关于python基础之装饰器详解的文章就介绍到这了,更多相关python装饰器内容请搜索 以前的文章或继续浏览下面的相关文章希望大家以后多多支持 !
最后更新于 2021-11-08 08:13:17 并被添加「」标签,已有 位童鞋阅读过。
本站使用「署名 4.0 国际」创作共享协议,可自由转载、引用,但需署名作者且注明文章出处
相关文章
- 脚踏钢琴婴儿健身架新生幼儿女踢宝宝躺着玩2踩3一6个月0-1岁玩具
- 什么是windows模块安装程序工作进程?可以删除吗?
- 双头棉签棒婴儿宝宝美容化妆棉棒口红掏耳朵尖头卸妆棉花棒
- 绿联适用苹果14钢化膜iPhone14promax手机膜14pro防窥膜14plus新款十四por高清贴膜13全屏覆盖ip防指纹pm保护
- Python requests timeout的设置