python的值对象
precious的Python项目详细描述
python的值对象。
示例
frompreciousimportValue,assign_attributesclassColor(Value):@assign_attributesdef__init__(self,red,green,blue,alpha=0):pass@propertydefgrayscale(self):return(self.r+self.g+self.b)/3
>>>red=Color(255,0,0)>>>redColor(255,0,0,0)>>>red==Color(255,0,0)True>>>Color.__slots__('red','green','blue','alpha')>>>hash(red)8736776571231852889
安装
pip install precious
用法
值对象类应该是基类ValueClass的子类。每个Value子类都必须定义attributes,这是一个包含所有属性名称的iterable。 这可以通过显式设置类的属性来实现:
classPoint(Value):attributes=('x','y')def__init__(self,x,y):self.x=xself.y=y
通过使用提供的一个helper decorators直接从__init__定义中提取属性名:
frompreciousimportValue,extract_attributesclassPoint(Value):@extract_attributesdef__init__(self,x,y):self.x=xself.y=y
使用快捷方式assign_attributes替换提取和分配__init__中所有属性的公共样板:
frompreciousimportValue,assign_attributesclassPoint(Value):@assign_attributesdef__init__(self,x,y):pass
注意,在上面的示例中,没有在父类的类__init__中分配属性,因此不需要super()调用。
测试
只需在包目录中运行tox:
$ tox
为什么不直接使用namedtuple?
对于简单的用例,namedtuple定义同样适用。
Point=namedtuple('Point',('x','y'))
不得不重复类名是一个小小的不公平,但定义是相当可读和简洁的。此外,类还可以获得迭代接口和索引支持,这有时是您想要的。但是,当需要默认值、方法或属性时,namedtuple的事情会变得非常糟糕。子类化是唯一的方法。考虑以下示例:
classColor(namedtuple('Color_',('r','g','b','alpha'))):__slots__=()def__new__(cls,r,g,b,alpha=0):returnsuper().__new__(cls,r,g,b,alpha)@propertydefgrayscale(self):return(self.r+self.g+self.b)/3# Equivalent toclassColor(Value):@assign_attributesdef__init__(self,red,green,blue,alpha=0):pass@propertydefgrayscale(self):return(self.r+self.g+self.b)/3
总之,扩展namedtuple的问题包括:
- 必须定义空的__slots__[1]。
- 当需要默认值时重写__new__。
- 在多个位置重复属性名称。
- 通过动态生成父类实现非初始化继承。
[1] | (1, 2)https://docs.python.org/3/reference/datamodel.html#slots |