python 描述符 继承_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类是独立进行类属性计数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值