python元编程之实现定制类--使用描述符,__slots__,__new__篇

问题:实现一个类,要求行为如同namedtuple:只存在给定名称的属性,不允许动态添加实例属性。

主要知识点在于: __slots__、描述符及property、__new__的使用

代码如下:

 1 """
 2 运行环境
 3 python 3.7+
 4 """
 5 from collections import namedtuple, OrderedDict
 6 
 7 #以下为要包装的对象:1个命名元组,用于存储计数,并对外传递信息
 8 Counter = namedtuple("Counter", "total put OK failed recorded keys count",
 9                      defaults=(0, 0, 0, 0, 0, 0, 0))
10 
11 class Demo:
12     """
13     使用__slots__,__new__及描述符实现定制类
14     只能使用Counter中的属性进行存取
15     """
16     #引入__slots__特殊属性用于控制实例属性
17     #_dict用于存储内部数据,此处未实现保护,可用定制描述符实现保护
18     __slots__ = list(Counter._fields)+['_dict']
19     def __new__(cls):
20         """
21         使用__new__特殊方法用于生成类实例之前配置类模板
22         因为描述符及特性(property)都是附在类上,而不是在实例上
23         """
24         for f in Counter._fields:
25             #动态生成描述符或特性,用于控制属性存取
26             #python内置的property就是特殊的描述符,可以用partialmethod包装后在此处使用.此处未展示
27             #自己实现描述符当然更具定制性
28             setattr(cls,f,Descriptor(f))
29         return super().__new__(cls)
30     def __init__(self):
31         self._dict={}
32         for f in Counter._fields:
33             self._dict[f]=0
34 
35     def update(self, n: Counter = None, **kargs):
36         """
37         使用数值累加计数器
38         当Counter与键参数同时提供时,键值为准
39         """
40         
41 #描述符实现
42 class Descriptor:
43     def __init__(self,storage_name:str):
44         self.storage_name=storage_name
45     def __set__(self,instance,value):
46         print('from descriptor..')
47         instance._dict[self.storage_name]=value
48     def __get__(self,instance,owner):
49         return instance._dict[self.storage_name]
50     
51 #也可以用以下特性工厂函数实现
52 def make_property(store_name:str)->property:
53     def getter(instance):
54         print('from property getter')
55         return instance._dict[store_name]
56     def setter(instance,value):
57         print('from property setter')
58         instance._dict[store_name]=value
59     return property(getter,setter)

补充说明,以上部分逻辑并未完整考虑和优化,只是对类定制及属性存取做实现演示。另外的实现方法可参考上篇:

python元编程之使用动态属性实现定制类--特殊方法__setattr__,__getattribute__篇 https://www.cnblogs.com/zward/p/10041162.html

猜你喜欢

转载自www.cnblogs.com/zward/p/10041453.html