zoukankan      html  css  js  c++  java
  • python 描述符+抽象类控制属性存取逻辑

    在上一篇博客中从类属性、实例属性、到特性、到描述符,创建了特性函数、描述符控制我们类的属性的一些数据验证,今天完成以下工作:

    • 描述符完成两件事:
      • 储存属性,以下使用Auto_Storage类
      • 验证属性,使用Validated验证doc是否为空字符串,weight、price属性是否为非负值,doc与weight、price均属于验证,具体怎么验证交由负责各自的验证类去处理故而此处采用了模板方法设计模式:一个模板方法用一些抽象的操作定义一个算法,而子类将重定义这些操作以提供具体的行为,所以我们需要用到抽象类(abc.ABC)

    代码实现

    import abc
    
    class Auto_Storage():
        __counter = 0
    
        def __init__(self):
            cls = self.__class__
            name = cls.__name__
            self.storagename = '_{}#{}'.format(name,cls.__counter)
            cls.__counter += 1
        def __get__(self, instance, owner):
            return  getattr(instance,self.storagename)  #返回一个value
    
        def __set__(self, instance, value):
            setattr(instance,self.storagename,value)  # setattr 相当于表达式:instance.__dict__[self.storagename] =value
    
    # instance 均代表LineItem类的实例
    #抽象类--模板,无法创建实例(继承自ABC抽象类)
    class Validated(abc.ABC,Auto_Storage):
        def __set__(self, instance, value):
            value1 = self.validate(value)   #这里self.validate 方法引用 需要在set value之前对value进行验证,所以我们需要重写__set__方法
            super().__set__(instance,value1)
    
    #定义抽象方法,有子类quantity、NoBlank内的方法完成具体实现
        @abc.abstractmethod
        def validate(self,value):  #对于validate 验证数据,在Validate中__set__方法覆盖父类方法,其中已经引入instance,故而此处只需要输入value参数就可以了
            "# 验证或者判断值是否大于0 写抽象办法"
    
    #具体实现验证非负值
    class quantity(Validated):  #get set分别继承自Auto_Storage 类、Validated类 --覆盖描述符
        def validate(self,value):
            if value>0:
                return value
            else:
                raise ValueError('Value must > 0')
    
    #具体实现验证空字符
    class NoBlank(Validated): #get set分别继承自Auto_Storage 类、Validated类--覆盖描述符
        def validate(self,value):
            if len(value) == 0:
                raise ValueError('The doc must not be empty')
            else:
                return value
    
    class LineItem():
        doc = NoBlank()
        weight = quantity()
        price = quantity()
    
        def __init__(self,doc,weight,price):
            self.doc = doc
            self.weight = weight
            self.price = price
    
        def subtotal(self):
            return self.doc*self.weight*self.price
    
    demo  =LineItem('lll',20,30)
    

    主要继承关系如下:

    类属性与继承类:

    • 类属性与继承:在Auto_Storage类中,__counter作为其类属性,为所有该类实例共享,但是在本例中quantity、NoBlank均继承自类Auto_Storage,届时会存在quantity、NoBlank两类实例,类属性:_Auto_Storage__counter 是否发生了 变化,发生了哪些变化?
    class Auto_Storage():
        __counter = 0   # 引用名称为:_Auto_Storage____counter
    
        def __init__(self):
            cls = self.__class__
            name = cls.__name__
            print(name)
            self.storagename = '_{}##{}'.format(name,cls.__counter)
            cls.__counter += 1
            print( self.storagename)
    
    class demo(Auto_Storage):
        pass
    
    class de(Auto_Storage):
        pass
    
    c = demo()
    a = de()
    c = demo()
    c = demo()
    

    图示如下:类demo、de、Auto_Storage各自拥有名为父类原始名称:_Auto_Storage____counter的类变量,所在上述实现代码中 quantity类与NoBlank类是独立进行类属性计数

    参考文章:python继承关系中,类属性的修改Python中的抽象类详解:abstractmethod、abc与真实子类

  • 相关阅读:
    SQL点滴34—SQL中的大小写
    js关闭和打开页面
    jquery处理checkbox
    CKeditor 配置使用
    .net4.0中的ClientIDMode
    FCKEditor使用说明
    SQL对Xml字段的操作 拓荒者
    c#中BackGroundWorker控件 拓荒者
    C#中DataGradView控件的常用操作 拓荒者
    JavaScript操作Xml 拓荒者
  • 原文地址:https://www.cnblogs.com/ivan09/p/14194987.html
Copyright © 2011-2022 走看看