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

    • 装饰器

      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,如果遇到同名属性,会用传入的属性覆盖原来的属性。

python学习之类的装饰器进阶版的更多相关文章

  1. Python学习笔记012——装饰器

    1 装饰器 1.1装饰器定义 在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator). 1.2 装饰器分类 装饰器:函数装饰器,类装饰器,函数的装饰器,类的装饰器 装饰器:函数装饰函 ...

  2. Python学习笔记:装饰器

    Python 装饰器的基本概念和应用 代码编写要遵循开放封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即: 封闭:已 ...

  3. python学习之day5,装饰器,生成器,迭代器,json,pickle

    1.装饰器 import os import time def auth(type): def timeer(func): def inner(*args,**kwargs): start = tim ...

  4. Python学习之路——装饰器

    开放封闭原则:不改变调用方式与源代码上增加功能 ''' 1.不能修改被装饰对象(函数)的源代码(封闭) 2.不能更改被修饰对象(函数)的调用方式,且能达到增加功能的效果(开放) ''' 装饰器 # 把 ...

  5. python学习笔记:装饰器2

    python的装饰器本质是函数,为了不改变装饰目标函数内部代码而增加额外功能而存在 一.一般装饰函数实例: import datetime def func_name(func):#定义一个装饰函数, ...

  6. Python学习——迭代器&生成器&装饰器

    一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...

  7. 从零开始的Python学习Episode 11——装饰器

    装饰器 装饰器是用来处理其他函数的函数,主要作用是在不修改原有函数的情况下添加新的功能,装饰器的返回值也是一个函数对象. 简单的装饰器 import time def show_time(f): de ...

  8. python学习笔记(五):装饰器、生成器、内置函数、json

    一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如说,我以前写了很多代码,系统已经上线了,但是性能比较不好,现在想把程序里 ...

  9. Python学习系列之装饰器

    装饰器的作用 装饰器用于装饰某个函数.方法或者类,它可以让这个函数执行之前或者执行之后做一些操作 手工实现一个装饰器 def outer(some_func): #装饰器 $1 def inner() ...

随机推荐

  1. Operating System:管程相关概念

    管程 (Moniters,也称为监视器)一.管程的概念是一种程序结构,结构内的多个子程序(对象或模块)形成的多个工作线程互斥访问共享资源.这些共享资源一般是硬件设备或一群变量.管程实现了在一个时间点, ...

  2. 微服务架构Day03-SpringBoot之web开发配置

    概述 SpringBoot开发: 1.创建SpringBoot应用,选中需要的场景模块. 2.SpringBoot已经默认将场景模块配置好,只需要在配置文件中指定少量的配置(数据库地址,用户名,密码) ...

  3. Linux内核4.19.1编译

    linux内核编译 1.1 大致步骤 下载linux内核4.19.1 官网链接: https://www.kernel.org/ 官网下载经常速度太慢,无法下载,提供另一个链接: http://ftp ...

  4. P3373 线段树2(多重标记线段树)题解

    题意: 操作有:区间加,区间乘,区间询问求和 思路: 设一个数为\(m*sum+a\),加就变成了\(m*sum+a+a_2\),乘就变成了\(m*m_2*sum+a*m_2\),所以我们设两个标记\ ...

  5. python xml转excle

    <?xml version="1.0" encoding="UTF-8"?> <RECORDS xmlns:xsi="http:// ...

  6. Kafka 博文索引

    博文索引 KafkaBroker 简析 KafkaConsumer 简析 KafkaProducer 简析 KafkaMirrorMaker 的不足以及一些改进 Kafka 简介 数据是系统的燃料,系 ...

  7. when I was installing github for windows ,some errors occurred !

    1: 2: 3: 4: install.log error messages:

  8. Google Developer Days 2019 & GDD

    Google Developer Days 2019 2019 Google 开发者大会 GDD Google Developer Days https://events.google.cn/intl ...

  9. how to install GitLab on Raspberry Pi OS

    how to install GitLab on Raspberry Pi OS GitLab & Raspberry Pi refs https://about.gitlab.com/ins ...

  10. Win/Mac 键位映射 & 在 Mac 上更改“键盘”偏好设置

    Win/Mac 键位映射 & 在 Mac 上更改"键盘"偏好设置 PC键盘 在Mac下Command/Option键切换 https://support.apple.com ...