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

Posted double大博

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了七天学会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()
      

    • 版本五--标准装饰器

      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()
      

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

      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()
      

以上是关于七天学会Python基础-第七天2/3-装饰器的主要内容,如果未能解决你的问题,请参考以下文章

七天学会Python基础-第七天3/3-自定义模块和random模块

python基础(第七天)

七天学会Python基础-第六天1/1

Python之第七天的努力--基础数据类型补充,编码进阶

Python之第七天的努力--基础数据类型补充,编码进阶

python学习第七天 基础数据类型补充 深浅copy 集合 关键字后面加可迭代对象