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

  • 相关阅读:
    Mybatis实现数据的增删改查(CRUD)
    Spring MVC基础入门
    Swap in C C++ C# Java
    java和c#使用hessian通信
    基于Netty4的HttpServer和HttpClient的简单实现
    RabbitMQ的几种典型使用场景
    java多线程编程
    singleton pattern的推荐实现
    python多线程编程
    基于GMap.Net的地图解决方案
  • 原文地址:https://www.cnblogs.com/zward/p/10041453.html
Copyright © 2011-2022 走看看