目录
一、前言二、高阶函数三、函数嵌套四、装饰器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没有实现
© 版权声明
THE END
暂无评论内容