装饰器可以修饰函数,同样,也可以修饰类

    • 装饰器

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

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

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

      结果就是:

      ======>被修饰的

    • 同样,装饰器装饰类的方式

    • @deco
      class Test:
          pass

      运行得到

      ======>被修饰的

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

    • 因为,对于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}

      目的很简单的达成了

    • 问题来了,代码要开放,如果我还有其他一百个类需要修改,偏偏每个类增加的内容还不一样,怎么办,现在这个装饰器,是写死了的,如果让这段代码更加灵活?

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

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

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

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

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

    • 换而言之,我传入其中的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,如果遇到同名属性,会用传入的属性覆盖原来的属性。

最新文章

  1. PowerDeigner 一个很好的画uml 和建模的软件
  2. Android 扫一扫----ZXing 的使用
  3. ssl创建自签名的https通信
  4. ffmpeg 音频转码
  5. Codeforces Round #206 (Div. 1)B(记忆化)
  6. MATLAB代码
  7. Swift中面向协议的编程
  8. android adb经常使用的命令
  9. 阿里云上给的防止跨站和xss攻击的代码
  10. Spring源码:IOC原理解析(一)
  11. Spring-Cloud(三)Eureka注册中心实现高可用
  12. 1005 继续(3n+1)猜想 (25 分)
  13. kNN处理iris数据集-使用交叉验证方法确定最优 k 值
  14. Django的学习(五)————实战问题
  15. tomcat 启动,停止,查看端口,日志位置
  16. Struts2 使用基本流程
  17. php 截取字符串第一个字符,截取掉字符串最后一个字符的方法
  18. VS2010程序调试
  19. Hbase Region Server整体架构
  20. android中HttpClient的应用(POST方法)

热门文章

  1. MySQL 误删用户故障解决方案
  2. 2019牛客多校第二场F Partition problem(暴搜)题解
  3. Redis五大类型及底层实现原理
  4. css background transparent All In One
  5. how to remove git commit history
  6. Scalability &amp; Scale-up &amp; Scale-out
  7. CI / CD in Action
  8. learning free programming resources form top university of the world
  9. xcode upgrade &amp; git bug
  10. 教你玩转CSS Overflow