装饰器的基础知识点
1.装饰器
- 开放封闭原则:
-
- 开放:对代码的扩展功能是开放的
- 封闭:对源码的修改时封闭的
- 装饰器:在不该变原函数的代码以及调用方式的前提下,为其增加新的功能。
- 装饰器就是一个函数,装饰器的本质就是一个闭包
- 写代码测试一下index函数的执行效率
import time
def index(): """ 有许多代码""" time.sleep(2) # 模拟的网络延迟或者代码效率 print("欢迎登录博客园首页") def timmer(f): f = index def inner(): start_time = time.time() f() end_time = time.time() print(f'测试本函数的执行效率{end_time-start_time}') return inner index = timmer() index()
分析代码的执行流程:
- 标准装饰器
import time def timmer(f): def inner(*args,**kwargs): start_time = time.time() v = f(*args,**kwargs) end_time = time.time() print(f'测试本函数的执行效率{end_time-start_time}') return v return inner @timmer # index = timmer(index) def index(): """ 有许多代码""" time.sleep(2) #模拟的网络延迟或者代码效率 print('欢迎登录博客园首页') return 666 ret = index() print(ret)
分析执行流程:
- 装饰器的基本的框架
def wrapper(func): def inner(*args,**kwargs): # 添加额外的功能:执行被装饰函数之前的操作 ret = func(*args,**kwargs) # 添加额外的功能:执行被装饰函数之后的操作 return ret return inner
2.装饰器的应用场景:
-
- 于用户认证
- 面向对象的类方法:classmethod
- 面向对象中的静态方法:staticmethod
- django框架中的中间件
- @crsf的认证
- flask框架的路由
3.一个装饰装饰多个函数:
status_dict = {"username": None, "status": False} def auth(f): """ 装饰器完成:访问被装饰函数之前,写一个登录认证的功能。 登录成功:让其访问被装饰得函数,登录没有成功,不让访问。 :param f: :return: """ def inner(*args, **kwargs): """ 访问函数之前的操作,功能 """ if status_dict["status"]: ret = f(*args, **kwargs) return ret else: username = input("请输入用户名").strip() password = input("请输入密码").strip() if username == "貂蝉" and password == "123": print("登录成功") status_dict['username'] = username status_dict['status'] = True ret = f(*args, **kwargs) return ret else: print("登录失败") return inner @auth def article(): print('欢迎访问文章页面') @auth def comment(): print('欢迎访问评论页面') @auth def dariy(): print('欢迎访问日记页面') article() comment() dariy()
4.多个装饰器装饰一个函数
def wrapper(func): def inner(*args, **kwargs): print("is 123") func(*args, **kwargs) print("345") return inner def wrapper1(func): def inner1(*args, **kwargs): print("7") func(*args, **kwargs) return inner1 def wrapper2(func): def inner2(*args, **kwargs): func(*args, **kwargs) print("15") return inner2 @wrapper2 @wrapper1 @wrapper # foo = wrapper(foo) def foo(): # 先执行里被装饰函数最近的那个装饰器 print("is foo") foo() # 执行结果为: 7 is 123 is foo 345 15
分析执行流程:
5.带参数的装饰器
def outer(flag): def timer(func): def inner(*args,**kwargs): if flag: print('''执行函数之前要做的''') re = func(*args,**kwargs) if flag: print('''执行函数之后要做的''') return re return inner return timer @outer(False) def func(): print(111) func()
待续