python基础之装饰器详解
目录
- 一、前言
- 二、高阶函数
- 三、函数嵌套
- 四、装饰器
- 4.1 被装饰方法带返回值
- 4.2 被装饰方法带参数
- 4.3 验证功能装饰器
- 4.4 验证功能装饰器——带参数
一、前言
装饰器:本质就是函数,功能是为其他函数添加附加功能
原则:
- 1、不修改被修饰函数的源代码
- 2、不修改被修饰函数的调用方式
装饰器 = 高阶函数 + 函数嵌套 + 闭包
二、高阶函数
高阶函数定义:
- 1、函数接收的参数是一个函数
- 2、函数的返回值是一个函数名
- 3、满足上述条件任意一个,都可以称为高阶函数
test 函数是高阶函数,接受了一个foo 作为参数
import time def 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 time def 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 func foo = 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 @timer def 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 @timer def 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_fun def index(): print("this is index") @auth_fun def home(): print("this is home page") @auth_fun def 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装饰器内容请搜索hwidc以前的文章或继续浏览下面的相关文章希望大家以后多多支持hwidc!