一、核心要义
描述符是对多个属性运用相同存取逻辑的一种方式。其是实现了特定协议的类,常见协议包括__get__,__set__,__delete__方法。上一章介绍的property类就实现了完整的描述符协议。
二、代码示例
1、LineItem类第3版
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/3/17 12:46
# @Author : Maple
# @File : 01-LineItem类第3版.py
# @Software: PyCharm
"""一个简单的描述符类"""
class Quantity:
def __init__(self,storage_name):
self.storage_name = storage_name
def __set__(self, instance, value):
if value > 0:
instance.__dict__[self.storage_name] = value
else:
raise ValueError('value must be >0')
class LineItem:
weight = Quantity('weight')
price = Quantity('price')
def __init__(self,description,weight,price):
self.description = description
# 这里赋值的时候,会访问描述符类的set方法
self.weight = weight
self.price = price
def subtotal(self):
return self.weight * self.price
def __repr__(self):
return 'LineItem =({},{},{})'.format(self.description,self.weight,self.price)
if __name__ == '__main__':
# 1.传入正常的值
com = LineItem('Computer',10,2000)
print(com) # LineItem =(Computer,10,2000)
# 2.weight负值测试
try:
com3 = LineItem('Computer', -10, 1000)
except ValueError as e:
print(e) # value must be >0
2、LineItem类第4版
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/3/17 9:36
# @Author : Maple
# @File : 02-LineItem类第4版.py
# @Software: PyCharm
"""自动获取存储属性的值"""
class Quantity:
__counter = 0
def __init__(self):
cls = self.__class__
prefix = cls.__name__
index = cls.__counter
self.storage_name = '_{}#{}'.format(prefix,index)
cls.__counter += 1
def __get__(self, instance, owner):
if instance is None:
# 通过托管类(此例中的LineItem)直接访问类属性时(此例中的weight和price时,instance为None,如果直接执行getattr,会报错
# 因此在此进行一下处理:直接返回描述符类
return self
else:
ret