zoukankan      html  css  js  c++  java
  • Python基础第七天:装饰器

    一,什么是装饰器

      装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象

      装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景

    二,装饰器的形成过程

      现在我有一个需求,我想让你测试这个函数的执行时间,在不改变这个函数代码的情况下:

      import time
    
      def func1():
          time.sleep(1)
          print('in func1')
    
      def timer(func):
          def inner():
              start = time.time()
              func()
              print(time.time() - start)
          return inner
    
      func1 = timer(func1)
      func1()
      in func1
      1.0000572204589844

      但是如果有多个函数,我都想让你测试他们的执行时间,你每次是不是都得func1 = timer(func1)?这样还是有点麻烦,因为这些函数的函数名可能是不相同,有func1,func2,graph,等等,所以更简单的方法,python给你提供了,那就是语法糖

      import time
    
      def timer(func):
          def inner():
              start = time.time()
              func()
              print(time.time() - start)
          return inner
    
      @timer   #==> func1 = timer(func1)
      def func1():
          time.sleep(1)
          print('in func1')
        
      func1()
      in func1
      1.0000574588775635

       刚刚我们讨论的装饰器都是装饰不带参数的函数,现在要装饰一个带参数的函数怎么办呢?

      import time
    
      def timer(func):
          def inner(name):
              start = time.time()
              func(name)
              print(time.time() - start)
          return inner
    
      @timer   #==> func1 = timer(func1)
      def func1(name):
          time.sleep(1)
          print('我的名字是,',name)
    
      func1('小红')
      我的名字是, 小红
      1.0000572204589844
      import time
    
      def timer(func):
          def inner(*args,**kwargs):
              start = time.time()
              func(*args,**kwargs)
              print(time.time() - start)
          return inner
    
      @timer   #==> func1 = timer(func1)
      def func1(name,hooby):
          time.sleep(1)
          print('我的名字是 %s,喜欢 %s' % (name,hooby))
    
      @timer   #==> func1 = timer(func1)
      def func2(name):
          time.sleep(1)
          print('我的名字是 %s' % (name))
    
      func2('小明')
      func1('小红','旅游')
      我的名字是 小明
      1.0000569820404053
      我的名字是 小红,喜欢 旅游
      1.0000574588775635

      上面的装饰器已经非常完美了,但是有我们正常情况下查看函数信息的方法在此处都会失效:

      def index():
          """这是一个主页信息"""
          print("from index")
    
      print(index.__doc__) #查看函数注释的方法
      print(index.__name__) #查看函数名的方法
      这是一个主页信息
      index

      如何解决呢?

      from functools import wraps
    
      def deco(func):
          @wraps(func)
          def wrapper(*args,**kwargs):
              return func(*args,**kwargs)
          return wrapper
    
    
      def index():
          """哈哈哈"""
          print("from index")
    
      print(index.__doc__)
      print(index.__name__)

    三,开放封闭原则

      1、对扩展是开放的

        为什么要对扩展开放呢?

        我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能;

      2、对修改是封闭的

        为什么要对修改封闭呢?

        就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户;

      装饰器完美的遵循了这个开放封闭原则;

    四,装饰器的主要功能和固定结构

    def timer(func):
        def inner(*args,**kwargs):
            '''执行函数之前要做的'''
            re = func(*args,**kwargs)
            '''执行函数之后要做的'''
            return re
        return inner
    from functools import wraps
    
    def deco(func):
      @wraps(func) #加在最内层函数正上方
        def wrapper(*args,**kwargs):
            return func(*args,**kwargs)
        return wrapper

    五,带参数的装饰器

      假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?

    一个一个的取消掉? 没日没夜忙活3天...

      过两天你领导想通了,再让你加上...

    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(True) #@outer(True) = @timer
    def func():
        print("1234567890")
    
    func()
    执行函数之前要做的
    1234567890
    执行函数后要做的

    六,多个装饰器装饰一个函数

    # 多个装饰器装饰同一个函数
    # 有些时候,我们也会用到多个装饰器装饰同一个函数的情况。
    
    def wrapper1(func):
        def inner():
            print('wrapper1 ,before func')
            func()
            print('wrapper1 ,after func')
        return inner
    
    def wrapper2(func):
        def inner():
            print('wrapper2 ,before func')
            func()
            print('wrapper2 ,after func')
        return inner
    
    @wrapper1
    @wrapper2
    def f():
        print('test ---------')
    
    f()
    wrapper1 ,before func
    wrapper2 ,before func
    test ---------
    wrapper2 ,after func
    wrapper1 ,after func
  • 相关阅读:
    【算法学习笔记】27.动态规划 解题报告 SJTU OJ 1254 传手绢
    【算法学习笔记】26.扫描维护法 解题报告 SJTU OJ 1133 数星星
    【算法学习笔记】25.贪心法 均分纸牌问题的分析
    【算法学习笔记】24.记忆化搜索 解题报告 SJTU OJ 1002 二哥种花生
    【算法学习笔记】23.动态规划 解题报告 SJTU OJ 1280 整装待发
    【算法学习笔记】22.算法设计初步 二分查找 上下界判断
    【算法学习笔记】21.算法设计初步 求第k个数 划分法 快排法
    【算法学习笔记】20.算法设计初步 归并排序 求逆序数
    【算法学习笔记】19.算法设计初步 最大子列和问题的几种方法
    【算法学习笔记】18.暴力求解法06 隐式图搜索2 八数码问题 未启发
  • 原文地址:https://www.cnblogs.com/nzd123456/p/8970331.html
Copyright © 2011-2022 走看看