python之三大法器——装饰器

  • 简单介绍闭包

  • # 定义一个函数
    def test(number):
    ​
    # 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
        def test_in(number_in):
            print("in test_in 函数, number_in is %d"% number_in)
            return number+number_in #number_in其实是一个函数的引用,是把函数的引用当做参数来传递
        # 其实这里返回的就是闭包的结果
        return test_in  #返回一定是内部函数的引用,不能带有小括号
    ​
    # 给test函数赋值,这个20就是给参数
    ret = test(20)        # 在这里执行的是test函数,然后将test_in函数的引用返回,重新赋值给ret
    # 注意这里的100其实给参数
    print(ret(100))   #在这里使用的ret(100)  相当于test_in(100)  也就相当于 test(20)(100) 最终返回的是 20+100
    #注 意这里的200其实给参数
    print(ret(200))   #在这里使用的ret(100)  相当于test_in(200)  也就相当于 test(20)(200) 最终返回的是 20+200
    • 由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存

  • 简单装饰器

    • 首先我们需要一个闭包

    • def test(fun):
          def test_in():
          #增加的功能
              print("这是我新增的功能")
              return  fun()    #一般我们把函数的结果返回,不会自己直接执行
          # 其实这里返回的就是闭包的结果
          return test_in#返回一定是内部函数的引用,不能带有小括号
    • @test
      def fun():
          return "rookieyu"
      print(fun())
    • 装饰器 @test

      • 相当于 fun = test(fun)

      • 在这里调用的test ,然后把fun这个函数当做一个对象传递给test函数,返回的是test_in函数重新赋值给fun

      • 最后我们在执行fun()的时候,相当于执行的是test(fun)() 是test_in函数。执行后会在函数里面先执行我们增加的功能,之后把函数之后的结果返回。

    • 简单的装饰器,函数没有参数传递

  • 简单装饰器的使用

  • 函数带参数装饰器

  • def debug(func):
        def wrapper(something):# 指定宇宙无敌参数
            print("[DEBUG]: enter {}()".format(func.__name__))
            print('Prepare and say...',)
            return func(something)
        return wrapper  # 返回
    ​
    @debug
    def say(something):
        print("hello {}!".format(something))
    say("rookieyu")
    • 当我们的函数有参数的时候,需要在闭包内部的函数里面接收参数

  • 通用装饰器

  • def debug(func):
        def wrapper(*args, *kwargs):# 指定宇宙无敌参数
            print("[DEBUG]: enter {}()".format(func.__name__))
            print('Prepare and say...',)
            return func(*args, *kwargs)
        return wrapper  # 返回
    • 我们采用的是*args, **kwargs,这样我们再调用装饰器的时候可以随意设置变量,让我们的装饰器更具有通用性

  • 给装饰器传递参数一:

    • def logging(level):
          def wrapper(func):
              def inner_wrapper(*args, **kwargs):
                  print("[{level}]: enter function {func}()".format(level=level,func=func.__name__))
                  return func(*args, **kwargs)
              return inner_wrapper
          return wrapper
      ​
      @logging(level='INFO')
      def say(something):
          print("say {}!".format(something))
      ​
      # 如果没有使用@语法,等同于
      # say = logging(level='INFO')(say)
      @logging(level='DEBUG')
      def do(something):
          print("do {}...".format(something))
      ​
      if __name__ =='__main__':
          say('hello')
          do("my work")
    • 采用三层函数嵌套的方式,最外层函数接收装饰器传递的参数

  • 给装饰器传递参数二:

  • # 当前装饰器无法对被装饰的函数参数进行验证
    def logging(level):
        def inner(fn):
            print(level)
            print("我的装饰器")
            return fn
        return inner
        
    @logging(level='INFO')
    def say(something):
        print("say {}!".format(something))
    • 注意,当前装饰器外层接收的是装饰器的参数,内层装饰器参数是传递的被装饰函数的引用。

  • 类装饰器

  • ​
    # 类装饰器
    class Decorator():
        def __init__(self,name):
            print(name)
    ​
        def __call__(self, *args, **kwargs):
            print("类装饰器")
            return args[0]
    ​
    ​
    @Decorator("rookieyu")
    def fun(a,b):
        print("这是函数")
    ​
    if __name__ == '__main__':
        fun(12,10)
    • 使用模仿函数call方法,让类成为一个装饰器

  • 给类里面函数加装饰器

    • # 给类的方法增加装饰器
      def wapper2(fn):
          def inner(self):
              #self指的是装饰的类
              print(self)
              print("给类增加装饰器")
              return fn(self)
          return inner
      ​
      class Demo():
          @wapper2
          def fun(self):
              print("这是当前类")
    • 给类里面函数添加装饰器需要注意的是第一个参数是self,指的是当前类

  • 给类增加装饰器

    • 和普通函数差不多使用,不用传递第一个参数。也可以传递一个参数cls,代表是的这个类

    • def wapper(fn):
          def inner(cls):
              print("给类增加装饰器",cls)
              return fn
          return inner
    • def wapper3():
          def inner(cls):
              print(cls)
              # 给雷增加属性
              cls.name = "rookieyu"
              return cls
          return inner
          
      @wapper3()
      class Demo():
          pass
  • 如果想给类动态增加类属性,那么我们装饰器就需要接收参数了

  • def wapper3(name):
        def inner(cls):
            print(cls)
            # 给雷增加属性
            cls.name = "rookieyu"
            return cls
        return inner
        
    @wapper3(name = 'rookie')
    class Demo():
        pass
        
    if __name__ == '__main__':
        print(Demo.name)

学IT,上博学谷

博学谷

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值