什么是装饰器?
装饰器顾名思义,一个可以起到装饰作用的工具
装饰器是谁? 装饰器本质还是一个函数,是一个嵌套的函数(闭包) 装饰器装饰谁? 装饰器(函数)是对现有函数功能的一个补充或增加,它可以更快速、更清晰、大批量的为函数增加功能,让代码更简单更易懂,再不变更原有函数代码的情况下为现有函数功能进行增强
关于函数闭包的概念
什么是闭包? 必须有一个嵌套函数(一个函数在另一个函数中) 这个嵌套函数(内函数)必须引用外部函数的变量 封闭函数必须返回嵌套函数
def outer_func(x): print(x) def inner_func(y): print x + y return inner_func
第一步理解 帮助理解装饰器的一个闭包函数:
def outer_func(): message = "hi 你好" def inner_func(): print(message) return inner_func() 调用:outer_func() 输出:hi 你好 def outer_func(): message = "hi 你好" def inner_func(): print(message) return inner_func 调用:my_func = outer_func() my_func() 输出:hi 你好
第二步理解 注意这次带参数了:
def outer_func(msg): message = msg def inner_func(): print(message) return inner_func *注意:这里return的是一个函数名字(实体),并没有(),换言之,他不会执行 调用: hello_func = outer_func("hello") python_func = outer_func("python") hello_func() python_func() 输出: hello python
第三步理解 注意,这次“接近”装饰器了!
不仅仅是“变量”可以作为参数传入函数,“函数”也可以作为参数传入函数
#做一个可以接收“函数”做为参数的函数 def deco_func(original_func): def wrapper_func(): return original_func() return wrapper_func #做一个独立函数 def show_age(): print("I am 18") 调用:deco_show_age = deco_func(show_age) deco_show_age 输出:I am 18
第四步理解 注意,这次是真的装饰器了!
#先创建装饰器,创建装饰器逻辑 def deco_func(original_func): def wrapper_func(): return original_func() return wrapper_func def show_age(): print("I am 18") 调用:deco_show_age = deco_func(show_age) deco_show_age() 输出:I am 18 #用装饰器去“装饰”,使用装饰器去装饰 def deco_func(original_func): def wrapper_func(): return original_func() return wrapper_func @deco_func def show_age(): print("I am 18") 调用:show_age() 输出: I am 18 特别注意! 装饰器装饰的函数,会先执行装饰器“函数”,在执行被装饰函数
第五步理解 继续推进-原始函数带参数怎么办?如何提升装饰器的宽容度
def deco_func(original_func): def wrapper_func(*args,**kwargs) return original_func(*args,**kwargs) return wrapper_func @deco_func def show_info(name,age): print(name,age) 调用:show_info("like",22) 输出:like 22
第六步理解 装饰器可否传入参数?提高装饰器的变通性
def deco_teacher(teacher_name): def school_teacher(original_func): def wrapper_func(name): return original_func(name + "老师是" + teacher_name) return wrapper_func return school_teacher @deco_teacher("郭老师") def stu1(): print("我叫",name) 调用:stu1("degang") 输出: 我叫 degang 老师是郭老师 @deco_teacher("岳老师") def stu2(): print("我叫",name) 调用:stu2("yunpeng") 输出: 我叫 yunpeng 老师是岳老师
#案例一 程序计时器 计算一段程序的执行时长 import time def timer(func): def wrapper(): start = time.time() func() end = time.time() return end - start return wrapper @timer def consumer1(): l_data = [] for x in range(1000000): l_data.append(x) @timer def consumer2(): time.sleep(2)
#案例二 登录控制 装饰器控制函数访问权限 def login_required(func): def wrapper(): pwd = input("请输入登录密码:") if pwd == "123": print("登录成功") func() else: print("密码错误,登录失败") return wrapper *执行直接进入 def admin_1(): print("您已经进入管理后台1") *询问密码 @login_required def admin_2(): print("您已经进入管理后台2")