python学习之类的装饰器进阶版

装饰器能够修饰函数,一样,也能够修饰类python

    • 装饰器闭包

      def deco(func):
          print('======>被修饰的')
      return func架构

    • 装饰器装饰函数的方式,语法糖函数

      @deco
      def test():
          print("这是函数")
      接下来运行,不调用:对象

      结果就是:作用域

      ======>被修饰的it

    • 一样,装饰器装饰类的方式for循环

    • @deco
      class Test:
          passclass

      运行获得test

      ======>被修饰的

    • 发现,修饰函数和修饰类,是同样的!

    • 由于,对于python而言,一切皆对象,函数是对象,类也是对象!

    • 上述装饰器均不严谨,图方便写的,实际写的时候,仍是须要遵循规则

    • 装饰器装饰 类,那么应该就是为 类 增长新的功能,至目前,咱们学过的对类进行操做,有对类中属性进行 增 删 改 查 的四个功能,那么,装饰器应该就是“增长”这一项了。如上,我类中直接pass,如何使用装饰器给他其中增长属性?

    • 在类外定义属性怎么办,类名+属性 = 值,例如:

      class Test:
          pass

      Test.x = 1
      Test.y = 2
      用__dict__查看其下属性内容
      print(Test.__dict__)

      结果以下:

      {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Test' objects>, '__weakref__': <attribute '__weakref__' of 'Test' objects>, '__doc__': None, 'x': 1, 'y': 2}

      咱们发现,x=1,y=2 被写进去了,

    • 接下来,咱们来写装饰器,给这个类增长属性

      def deco(obj):

          obj.x = 1
          obj.y = 2
          obj.z = 3
          return obj

      @deco
      class Test:
          pass

      查看其下属性

      print(Test.__dict__)

      结果为:{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Test' objects>, '__weakref__': <attribute '__weakref__' of 'Test' objects>, '__doc__': None, 'x': 1, 'y': 2, 'z': 3}

      目的很简单的达成了

    • 问题来了,代码要开放,若是我还有其余一百个类须要修改,恰恰每一个类增长的内容还不同,怎么办,如今这个装饰器,是写死了的,若是让这段代码更加灵活?

    • 同时,咱们对比下装饰器的原则:

      一、不改变被修饰函数的源代码:√

      二、不改变被修饰函数的调用方法:√

            类的实例化就一种,,,没什么改不改的

      也就是说,上面这段装饰器代码,是合格的,接下来就是怎么加工,让他更加灵活!

    • 换而言之,我传入其中的x y z 几个参数,须要由我指定也就是说,要由我来输入代码中,但这段代码的参数,已经有了,是语法糖的规则,类名。

    • 那么,我学函数装饰器同样,在装饰器内部嵌套一层呢?

      很惋惜,外部做用域,没法获取内部做用域的变量值

    • 往左不行,那就往右,我在他外面嵌套一层,把参数传到他的上一层做用域,他做为内层来获取上层总能够了吧!

    • def ti(**kwargs)由于属性都是关键字参数,这里直接用kwargs

      为了运行内部代码,须要使用闭包外层返回的值应该为内部函数名deco

      初步代码架构以下:

      def ti(**kwargs):
          def deco(obj):
              return obj
          return deco

      接下来,咱们须要改写内部函数,让内部函数获取外部函数传入的关键字参数,须要挨个取出来,放进函数中去做为属性。

      emmmmmmmmmmmmmmmmmmmmm,挨个取出来,我想到了for循环

      for key,value in kwargs.items()

      用for循环取出其中的key值和value值,接下来,就是把它放进去类里面做为属性了。

    • 增长属性的方法是什么来着,设置attr,即setattr

      setattr(obj,key,value)

    • 把上述代码整合下:

      def ti(**kwargs):
          def deco(obj):
              for key,value in kwargs.items():
                  setattr(obj,key,value)
              return obj
          return deco

      这里要注意的,ti函数是有传入值的,这个传入值,那么在修饰类的时候,这里传入的,就应该是属性的名和属性值

      @ti(x= 1)

      class Test:
          pass

    • 咱们再反过来检查下代码:

      @是语法糖,自己实际上是个赋值操做,这一步是从右边往左边运行,应该是这样的内容

      Test = ti(x = 1)(Test)

      依次运行上述内容,先来ti(x=1)其返回值是deco,这段代码其实就是Test = deco(Test),也就是@deco,x = 1 这个参数传入后,在最外层并无用,而是在内部的时候使用for循环从字典{'x' : 1}中取出来,在经过setattr方法来增长到类当中

    • 须要注意的是,setattr,若是遇到同名属性,会用传入的属性覆盖原来的属性。

相关文章
相关标签/搜索