zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    CentOS重启与关机
    VIM打开文件与保存文件
    sql Split
    JS获取URL参数
    C#后台调用公网接口(GET, POST)
    鼠标右击.exe的程序出现闪退(桌面重启)怎么办
    JS判断有无网络(移动端)
    TFS API : 四、工作项查询
    TFS API:三、TFS WorkItem添加和修改、保存
    TFS API:二、TFS 代码查询工作项
  • 原文地址:https://www.cnblogs.com/zward/p/10041453.html
Copyright © 2011-2022 走看看