装饰器

匿名 (未验证) 提交于 2019-12-02 22:11:45
  1. 开放封闭原则
  • 开放:对代码的拓展开放的,允许代码扩展、添加新功能。如更新地图,加新枪,等等。
  • 封闭:对源码的修改是封闭的。

    装饰器

  • 装饰器:完全遵循开放封闭原则。
  • 装饰器: 在不改变原函数的代码以及调用方式的前提下,为其增加新的功能。
  • 装饰器就是一个函数。

    • 版本一: 写一些代码测试一下index函数的执行效率。
    import time  def index():      '''有很多代码.....'''      time.sleep(2) # 模拟的网络延迟或者代码效率      print('欢迎登录博客园首页')   def dariy():      '''有很多代码.....'''      time.sleep(3) # 模拟的网络延迟或者代码效率      print('欢迎登录日记页面')  # print(time.time())  # 格林威治时间。 # 版本一有问题: 如果测试别人的代码,必须重新复值粘贴。 start_time = time.time() index() end_time = time.time() print(end_time-start_time) #结果: 欢迎登录博客园首页 2.0004754066467285  start_time = time.time() dariy() end_time = time.time() print(end_time-start_time) #结果: 欢迎登录日记页面 3.0002753734588623 
    • 版本二:利用函数,解决代码重复使用的问题

      import time def index():     '''有很多代码.....'''     time.sleep(2) # 模拟的网络延迟或者代码效率     print('欢迎登录博客园首页')  def timmer(f):  # f= index 传参     start_time = time.time()     f()  # index()     end_time = time.time()     print(f'测试本函数的执行效率{end_time-start_time}')  timmer(index)  #index()--->原函数的调用方式  版本二还是有问题: 原来index函数源码没有变化,并给原函数添加了一个新的功能:测试原函数的执行效率。 满足开放封闭原则么?不满足,因为原函数的调用方式改变了。 
    • 版本三:不能改变原函数的调用方式。

       import time  def index():      '''有很多代码.....'''      time.sleep(2) # 模拟的网络延迟或者代码效率      print('欢迎登录博客园首页')  #timmer()是一个装饰器,本质是:  闭包 def timmer(f):  # f = index  (funciton index123)内存地址      def inner():  # inner :(funciton inner123)          start_time = time.time()          f()  # index() (funciton index123)          end_time = time.time()          print(f'测试本函数的执行效率{end_time-start_time}')      return inner  # (funciton inner123) index = timmer(index)  # inner (funciton inner123) index()  # inner()   def func():    print('in func')  func() #函数名func指向内存地址 func = 666  #func指向666 func(0)#报错 
    • 版本四:具体研究

    • 版本五:python做了一个优化;提出了一个语法糖的概念。 标准版的装饰器

      import time # timmer装饰器 --->装饰器放在所有函数最上面 def timmer(f):     def inner():         start_time = time.time()         f()         end_time = time.time()         print(f'测试本函数的执行效率{end_time-start_time}')     return inner  @timmer #  @timmer读两行,相当于index = timmer(index)  def index():     '''有很多代码.....'''     time.sleep(0.6) # 模拟的网络延迟或者代码效率     print('欢迎登录博客园首页') index() #结果: 欢迎登录博客园首页 测试本函数的执行效率0.6001222133636475  
    • 版本六:被装饰的函数带返回值

      import time # timmer装饰器 def timmer(f): # f = index     def inner():         start_time = time.time()          r = f()  # index()         end_time = time.time()         print(f'测试本函数的执行效率{end_time-start_time}')         return r  #加上此句     return inner  @timmer # index = timmer(index) def index():     '''有很多代码.....'''     time.sleep(0.6) # 模拟的网络延迟或者代码效率     print('欢迎登录博客园首页')     return 666 ret = index()  # inner() print(ret) #结果: 欢迎登录博客园首页 测试本函数的执行效率0.6007750034332275 666 # 加上装饰器不应该改变原函数的返回值,所以666 应该返回给我下面的ret,但是下面的这个ret实际接收的是inner函数的返回值,而666真正返回给的是装饰器里面的f() 也就是 r,我们现在要解决的问题就是将r给inner的返回值,所以变成 inner函数的返回值为 return r。 
    • 版本七:被装饰的函数带参数

      import time # timmer装饰器 def timmer(f):   # f = index     def inner(*args,**kwargs):         #  函数的定义:* 聚合  args = ('李舒淇',18)         start_time = time.time()         r = f(*args,**kwargs) # 给def index(name,age)传参         # 函数的执行:* 打散:f(*args) --> f(*('李舒淇',18))  --> f('李舒淇',18)         end_time = time.time()         print(f'测试本函数的执行效率{end_time-start_time}')         return r     return inner  @timmer # index = timmer(index) def index(name,age):   #     '''有很多代码.....'''     time.sleep(0.6) # 模拟的网络延迟或者代码效率     print(f'欢迎{age}岁{name}登录博客园首页')     return 666 index('李舒淇',18)  # inner('李舒淇',18) #结果: 欢迎18岁李舒淇登录博客园首页 测试本函数的执行效率0.6005463600158691
      标准版的装饰器;  def wrapper(f):     def inner(*args,**kwargs):         '''添加额外的功能:执行被装饰函数之前的操作'''         ret = f(*args,**kwargs)         ''''添加额外的功能:执行被装饰函数之后的操作'''         return ret     return inner 
  1. # 装饰器的应用:登录认证。模拟博客园登录的作业。装饰器的认证功能。 #程序框架:   def login():     pass   def register():     pass   status_dict = {     'username': None,     'status': False, }  def auth(f):     '''     你的装饰器完成:访问被装饰函数之前,写一个三次登录认证的功能。     登录成功:让其访问被装饰得函数,登录没有成功,不让访问。     :param f:     :return:     '''     def inner(*args,**kwargs):         '''访问函数之前的操作,功能'''         if status_dict['status']:  #即status_dict['status']对应的值为True             ret = f(*args,**kwargs)             '''访问函数之后的操作,功能'''             return ret         else:             username = input('请输入用户名').strip()             password = input('请输入密码').strip()             if username == 'taibai' and password == '123':                 print('登录成功')                 status_dict['username'] = username                 status_dict['status'] = True                 ret = f(*args, **kwargs)                 return ret             else:                 print('登录失败')     return inner @auth  # article = auth(article) def article():     print('欢迎访问文章页面') @auth def comment():     print('欢迎访问评论页面') @auth def dariy():     print('欢迎访问日记页面')  article()  # inner() comment()  #inner() dariy()   #inner  #结果: 请输入用户名taibai 请输入密码123 登录成功 欢迎访问文章页面 欢迎访问评论页面 欢迎访问日记页面
文章来源: 装饰器
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!