七天学会Python基础-第七天2/3-装饰器

装饰器:装饰器的本质是闭包

  • 定义:

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

    • 开放:对代码的拓展是开放的,更新地图,加新枪,等等
    • 封闭:对源码的修改十封闭的,
      • 就是一个功能,一个函数。
    • 装饰器:完全遵循开放封闭原则。
  • 测试index函数的执行效率

    • 版本一有问题:如果测试别人的代码,必须重新赋值粘贴

      def index():
          '''
          有很多代码
          '''
          time.sleep(3)
          print("欢迎登陆博客园!")
      import time
      print(time.time())	# 格林威治时间。
      start_time=time.time()
      index()
      end_time=time.time()
      
    • 版本二:解决代码重复使用的问题

      def timmer(f):
          start_time=time.time()
          f()
          end_time=time.time()
          print(f"测试本函数的执行效率{end_time-start_time}")
      timmer(index)
      # 版本二还是有问题:原来index函数源码没有变化,给源函数添加了一个新的功能,测试原函数的执行效率的功能
      #不满足开放封闭原则,因为原函数的调用方式变了
      
    • 版本三:不能改变原函数的调用方式------------原生态修饰器

      def timmer(f):
          def inner():
              start_time=time.time()
      		f()
          	end_time=time.time()
          	print(f"测试本函数的执行效率{end_time-start_time}")
          return inner
      # ret=timmer(index)	# inner
      # ret() # inner()
      ret=timmer(index)
      index=timmer(index)
      
    • 版本四:具体研究

      def index():
      #     有很多代码
          time.sleep(3)
          print("欢迎登陆博客园!")
      def timmer(f):
          # 相当于创建了一个*变量 f=index  # index的内存地址
          def inner():
              start_time=time.time()
      		f()
          	end_time=time.time()
          	print(f"测试本函数的执行效率{end_time-start_time}")
          return inner
      index=timmer(index)
      index()
      

    七天学会Python基础-第七天2/3-装饰器

    • 版本五--标准装饰器

      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  # 等同于index=timmer(index),需要将@装饰器名字放在被装饰的函数前面,因为读到这里的时候,解释器会向下多读一行,
      def index():
          # 很多代码
          time.sleep(2)  # 模拟网络延迟或者代码效率
          print("欢迎登陆博客园首页")
      index()
      

      七天学会Python基础-第七天2/3-装饰器

    • 版本六--被装饰函数带返回值

      import time
      # timmer装饰器写再在最上面
      def timmer(f):
          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(2)  # 模拟网络延迟或者代码效率
          print("欢迎登陆博客园首页")
          return 666
      # 加上装饰器不应该改变原函数的返回值,所以666应该返回给我下面的ret,
      # 但是下面的ret实际接受的是inner函数的返回值,而666返回给的是装饰器里面的f()
      # 也就是r,我们现在要解决的问题就是将r给inner的返回值
      ret=index()
      print(ret)
      
    • 版本七--被装饰函数带参数(最标准的)

      import time
      # timmer装饰器写再在最上面
      def timmer(f):
          def inner(*args,**kwargs):
              # 函数的调用:*聚合args=('taibai',18)
              start_time = time.time()
              r=f(*args,**kwargs) # 真正的index执行者
              # 函数的执行:*打散:f(iterable)-->f(*('taibai',18))-->f('taibai',18)
              end_time = time.time()
              print(f"{end_time - start_time}")
              return r
          return inner
      @timmer  # 等同于index=timmer(index),需要将@装饰器名字放在被装饰的函数前面,因为读到这里的时候,解释器会向下多读一行,
      def index(name):
          # 很多代码
          time.sleep(2)  # 模拟网络延迟或者代码效率
          print(f"欢迎{name}登陆博客园首页")
      index("纳钦") # inner()
      -------------------------------------------
      def dariy(name,age):
          time.sleep(1)
          print(f"欢迎{age}岁的{name}登陆日记页面")
      dariy('taibai',18)
      
    • 标准版的装饰器:

      def wrapper(f):
          def inner(*args,**kwargs):
              """添加额外的功能,执行被装饰函数之前的操作"""
              ret=f(*args,**kwargs)
              """添加额外的功能,执行被装饰函数之后的操作"""
          return inner
      
  • 装饰器的应用

    1. 登录认证

      def login():
          print("请完成登录功能")
      def register():
          print('请完成注册功能')
      
      status_dic={
          'username':None,
          'status':False
      }
      def auth(f):
          '''
          你的装饰器完成:访问被装饰函数之前,写一个三次认证的功能
          登陆成功,让其访问被装饰的函数,登录没有成功,不让访问。
          :param f:
          :return:
          '''
          def inner(*args,**kwargs):
              '''访问函数之前的操作。功能'''
              if status_dic['status']:
                  ret=f(*args,**kwargs)
                  return ret
              else:
                  username=input("请输入用户名")
                  password=input("请输入密码")
                  if username=='taibai' and password=='123':
                      print("登陆成功")
                      status_dic['username']=username
                      status_dic['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()
      dariy()
      
上一篇:JavaSE-12.2.2【局部内部类】


下一篇:排序算法