专栏首页python3python_类装饰器

python_类装饰器

一.定义 装饰器就是一个给对象添加额外功能的函数,其本质是函数。它的基本构造:高阶函数+函数嵌套+闭包。 二.简单类的装饰器 我们先看简单的类的装饰器,如果我们需要给任意一个类添加一个打印功能,即:没当操作这个类时,就打印”定义了一个装饰类函数”,见下图:

@Decorator #相当于执行 School = Decorator(School) 上面代码块为:

#给每个类打印一句话
def Decorator(obj):
    print("定义了一个装饰器函数")
    return obj

@Decorator          #相当于执行 School = Decorator(School)
class School():
    pass
            如果我们要给该类添加一个数据属性和一个函数属性,又该如何定义这个装饰器呢?见下图:

代码块如下:

#给每个类添加一个数据属性和一个函数属性
def Decorator(obj):# print(School.__dict__)
    #添加数据属性
    obj.addr = "浙江省杭州市"
    def price():
        pass
    #添加函数属性
    obj.price = price
    return obj

@Decorator          #相当于执行 School = Decorator(School)
class School():
    def __init__(self,name,price):
        self.name =name
        self.price =price

#打印类的属性字典
print(School.__dict__)

三.高级类的装饰器 此时,在实际场景中可能需要在装饰器中使用变量参数,那么该如何实现呢? 在二中只利用了装饰器中的高阶函数的概念,要实现上述的需求,就需要使用装饰器构造的另外两部分:函数嵌套、闭包。如下图所示,我们需要给类添加一个数据属性,但是此时不同的类要求添加的属性是可变的,处理方法见下图:

多个类使用该装饰器添加不同的属性,如下图:

该部分代码块如下:

#给每个类添加一个可变的数据属性
def Decorator(**kwargs):
    def add(obj):
        "添加数据属性"
        # print('调用外部函数的**kwargs',kwargs)
        for key,val in kwargs.items():
            # 添加数据属性
            setattr(obj,key,val)
        return obj
    # print("外部传入的参数为:",kwargs)
    return add

@Decorator(addr = "浙江省杭州市",name ="浙江大学")          #执行顺序:1.运行Decorator函数,先打印外部的传入的参数,返回add函数名;2.再执行School = add(School)
class School():
    def __init__(self,price):
        self.price =price

@Decorator(addr = "湖北省",price =12000)
class School1():
    pass

print(School.__dict__)
print(School1.__dict__)

四.类的装饰器在实际中的应用 我们在学习类时,介绍了类的静态属性(参考https://blog.51cto.com/10836356/2108790),当时就猜测到,是利用的装饰器来完成该功能。那么到底是怎么实现的呢?见下文:

在上面的代码中,静态属性的属性是由python内部自己给我们实现的,那么到底它是怎么工作的呢?见下图:

此时我们还未进行实例化及调用类的静态属性,见下图:

我们可以看到,当进行实例化时,并没有明显差异,但是当调用类的total方法时,就会去调用Myproperty类中的get()方法(此处用到的是描述符优先级的知识,将另开篇幅讲解,此处直接应用),为达到理想的效果,我们只需在get()中进行处理就好,如下图进一步处理:

至此,该部分的功能已经完全实现。这就是python在为我们做的工作。那么我们已经理解了原理,这样我们就可以自定义类的其他装饰器。 该部分代码块如下:

class Myproperty():
    def __init__(self,fun):
        # print("执行Myproperty类的构造方法")   #调用Myproperty类时会首先运行它
        self.fun = fun
    def __get__(self, instance, owner):
        """
        :param instance: 代表school实例本身
        :param owner:  代表类School本身
        :return:
        """
        # print('调用Myproperty的属性时将执行此方法')
        return  self.fun(instance)

class School():
    """
    @name:学校名字
    @addr:学校地址
    @price:学费
    @num:招生人数
    """
    def __init__(self,name,addr,price,num):
        self.name =name
        self.addr =addr
        self.price =price
        self.num =num
    # @property
    @Myproperty    #等价于-->>total=Myproperty(total)
    def total(self):
        "求总的学费"
        return  self.price*self.num

school = School('浙江大学','浙江省杭州市',12000,6000)
print(school.total)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python 小点心---获取当前函数名

    python 具有强大的自省能力,在函数运行时,可以在函数内部获取到当前所在的函数名称,请看示例代码

    py3study
  • python终极篇 --- django

    HttpResponse('字符串')   ——》 页面显示字符串的内容   render(request,'模板的名字',{k1:v1})  ——》 整个HT...

    py3study
  • gtk3示例--buttonbox

    py3study
  • 程序猿都没对象,JS竟然有对象?

      现在做项目基本是套用框架,不论是网上的前端还是后端框架,也会寻找一些封装好的插件拿来即用,但还是希望拿来时最好自己过后再回过头了解里面的原理,学习里面优秀的...

    欢醉
  • Serverless(无服务)基础知识

    链接 | juejin.im/post/5d42945ff265da03a715b2f0

    五月君
  • Python发送Http请求时,中文乱码

    quote():假如URL的 name 或者 value 值中有『&』、『%』或者『=』等符号,就会有问题。所以URL中的参数字符串也需要把『&=』等符号进行编...

    py3study
  • 详说tcp粘包和半包

    tcp服务端和客户端建立连接后会长时间维持这个连接,用于互相传递数据,tcp是以流的方式传输数据的,就像一个水管里的水一样,从一头不断的流向另一头。

    lpxxn
  • 专属|Arch Linux 软件库现恶意程序

    近日,鲜为人知的网络间谍组织BlackTech被发现使用了友讯科技的证书签名其恶意程序。安全研究员称,证书被用于签名两个恶意负荷,第一个是PLEAD后门,第二个...

    漏斗社区
  • python 解析 eml文件

    py3study
  • 这大概是小游戏开放注册后的第一辆车!不上你就亏了

    知晓君

扫码关注云+社区

领取腾讯云代金券