zoukankan      html  css  js  c++  java
  • 通过描述符自定制@property的功能

    # 通过描述符自定制@property的功能
    
    # 原始通过@property实现的功能:将类中定义的函数属性,通过装饰器@property将其封闭成数据属性
    
    class Room:
        def __init__(self, name, width, length):
            self.name = name
            self.width = width
            self.length = length
    
        @property
        def area(self):
            return self.width * self.length
    
    
    r1 = Room('厨房', 10, 4)
    print(r1.area)
    
    
    # 通过描述符与装饰器自定制@property的功能
    
    class Lazyproperty:  # 定义描述符的类
        def __init__(self, func):  # 初始化时接收传入的方法进行保存
            self.func = func
    
        def __get__(self, instance, owner):
            if instance is None:    # 解决直接用类调用属性时传不了实例而报错的问题
                return self
            res = self.func(instance)
            setattr(instance, self.func.__name__, res)  # 将res放入实例的字典中,如果下次再调用,根据优先级实例属性高于非数据描述符,实例的属性字典中有就直接从实例的属性字典中找了
            return res  # 返回实例对象调用父类方法的结果,instance代表实例
    
    
    class Room2:
        def __init__(self, name, width, length):
            self.name = name
            self.width = width
            self.length = length
    
        @Lazyproperty   # area=Lazyproperty(area) 使用装饰器的这一步就相当于对area属性指定了描述符,给Room2添加了一个类属性
        def area(self):
            return self.width * self.length
    
    r2 = Room('厨房', 10, 4)
    # 实例调用area
    print(r2.area)  # 从r2中先找有没有area属性,没有从父类Room2中找,找到后发现是非数据描述符,就触发了__get__方法
    # 类调用area
    print(Room2.area)   # 由于__get__方法的接收参数需要一个实例,这里是用类调用的,所以会传None过去,因此会报错
  • 相关阅读:
    构建maven项目,自定义目录结构方法
    Nginx反向代理实现负载均衡以及session共享
    Spring Boot 2.x引入JS,CSS 失效问题
    WebMvcConfigurerAdapter已过时
    闲谈Tomcat性能优化
    oracle decode函数和 sign函数
    为什么要使用MQ和到底什么时候要使用MQ
    redis持久化的几种方式
    【mySQL】left join、right join和join的区别
    redis缓存在项目中的使用
  • 原文地址:https://www.cnblogs.com/dangrui0725/p/9471820.html
Copyright © 2011-2022 走看看