首页 > 其他分享 >混合类Mixins介绍

混合类Mixins介绍

时间:2023-04-07 14:56:42浏览次数:36  
标签:__ .__ self Mixins 介绍 混合 setitem key cls

介绍

混合类是封装了一些通用行为的基类,旨在重用代码。通常,混合类本身并没有什么用,仅扩展这种类也行不通
因为在大多数情况下,它都依赖于其它类中定义的方法和属性。通过多继承,可将混合类与其它类一起使用,从而
让混合类的方法或属性变得可用。

示例

假设有一个简单的分析器,它接收一个字符串,并迭代该字符串中由连字符(-)分隔的值:
class BaseTokenizer:
  def __init__(self, str_token):
    self.str_token = str_token

  def __iter__(self):
    yield from self.str_token.split("-")

>>> tk = BaseTokenizer("28a2320b-fd3f-4627-9792-a2b38e3c46b0")
>>> list(tk)
['28a2320b', 'fd3f', '4627', '9792', 'a2b38e3c46b0']

拓展上述需求

现在我们要在不修改这个基类的情况下,以大写的方式发送各个值,就这个简单的示例而言,
可创建一个新类,但假设有大量的类拓展了BaseTokenizer,而我们又不想替换所有这些类。
为此,可在层次结构中混入一个处理这种变化的新类:
class UpperIterableMixin:
  def __iter__(self):
    return map(str.upper, super().__iter__())

class Tokenizer(UpperIterableMixin, BaseTokenizer):
  pass

新的Tokenizer类非常简单,不需要有任何代码,因为它利用了混合类。这种混合类相当于一个装饰器。从前面
的介绍可知,Tokenizer从混合类那里获得方法__iter__,而这个方法通过调用supper()将职责委托给了下一个类
BaseTokenizer,同时将返回的值转换为答谢,从而实现了所需的效果。

示例

假设你想扩展映射对象,给它们添加日志,唯一性设置,类型检查等功能,下面是一些混入类

class LoggedMappingMixin:
    __slots__ = ()
    
    def __getitem__(self, key):
        print("Getting" + str(key))
        return super().__getitem__(key)
    
    def __setitem__(self, key, value):
        print("Setting {} = {!r}".format(key, value))
        return super().__setitem__(key, value)
    
    def __delitem__(self, key):
        print("Deleting" + str(key))
        return super().__delitem__(key)
    

class SetOnceMappingMixin:
    __slots__ = ()
    
    def __setitem__(self, key, value):
        if key in self:
            raise KeyError(str(key) + 'already set')
        return super().__setitem__(key, value)
    

class StringKeysMappingMixin:
    __slots__ = ()
    
    def __setitem__(self, key, value):
        if not isinstance(key ,str):
            raise TypeError('keys must be strings')
        return super().__setitem__(key ,value)

通过多继承和其它映射对象混入使用

如上这些类单独使用起来没有任何意义,事实上如果你去实例化任何一个类,除了
产生异常外没有任何作用。他们是用来通过多继承和其它映射对象混入使用的
class LoggedDict(LoggedMappingMixin, dict):
  pass

d = LoggedDict()
d["x"] = 23
print(d["x"])
del d["x"]


from collections import defaultdict
class SetOnceDefaultDict(SetOnceMappingMixin, defaultdict):
  pass

d = SetOnceDefaultDict(list)
d["x"].append(2)
d["x"].append(3)

讨论

混入类在标准库中很多地方都出现过,通常都是用来像上面那样拓展某些类的功能
他们也是多继承的一个主要用途。比如,当你编写网络代码时候,你会经常使用
`socketserver`模块中的`ThreadingMixIn`来给其它网络相关类增加多线程支持。

例如:下面是一个多线程的XML-RPC服务:
from xmlrpc.server import SimpleXMLRPCServer
from socketserver import ThreadingMixIn
class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
  pass

同时在一些大型库和框架中也会发现混入类的使用,用途同样是增强已存在的类的功能和一些可选特征。

对于混入类,有几点需要记住。首先是,混入类不能直接被实例化使用。 其次,混入类没有自己的状态信息,也就是说它们并没有定义 __init__() 方法,并且没有实例属性。 这也是为什么我们在上面明确定义了 __slots__ = () 。

还有一种实现混入类的方式就是使用类装饰器

def LoggedMapping(cls):
    """第二种方式:使用类装饰器"""
    cls_getitem = cls.__getitem__
    cls_setitem = cls.__setitem__
    cls_delitem = cls.__delitem__

    def __getitem__(self, key):
        print('Getting ' + str(key))
        return cls_getitem(self, key)

    def __setitem__(self, key, value):
        print('Setting {} = {!r}'.format(key, value))
        return cls_setitem(self, key, value)

    def __delitem__(self, key):
        print('Deleting ' + str(key))
        return cls_delitem(self, key)

    cls.__getitem__ = __getitem__
    cls.__setitem__ = __setitem__
    cls.__delitem__ = __delitem__
    return cls


@LoggedMapping
class LoggedDict(dict):
    pass

标签:__,.__,self,Mixins,介绍,混合,setitem,key,cls
From: https://www.cnblogs.com/weiweivip666/p/17296154.html

相关文章

  • Java 自增自减运算符和移位运算符介绍
    摘自JavaGuide(「Java学习+面试指南」一份涵盖大部分Java程序员所需要掌握的核心知识。准备Java面试,首选JavaGuide!)自增自减运算符在写代码的过程中,常见的一种情况是需要某个整数类型变量增加1或减少1,Java提供了一种特殊的运算符,用于这种表达式,叫做自增运算符(++)和自......
  • HDFS存储介绍
    1:datanode数据节点-存放数据的2:namenode 名字节点-主要是存放元数据的,比如:文件大小 名称存放位置等3:secondarynamenode是存放fimage信息的,具体解释如下:namenode   fimage   editlognamenode中每次有信息变化的时候,都会放到editlog中,然后由editlog同步......
  • 储能控制器,simulink仿真模型。 采用下垂控制实现蓄电池超级电容构成的混合储能功率分
    储能控制器,simulink仿真模型。采用下垂控制实现蓄电池超级电容构成的混合储能功率分配、SOC均衡控制、考虑线路阻抗情况下提高电流分配精度控制、母线电压补控制。YID:2580685477458200......
  • haoop的相关介绍及概念
    文章目录前言hadoop介绍Hadoop的集群优点:关于hadoop的相关概念:分布式存储:命名空间主从节点:Block容灾前言cluster:集群LB:负载均衡LVSSLBHAPROXY,nginxHA:高可用MHA,keepalived,hearebeatHPC:Hadoop:大批量的计算辅助存储和运算什么是分布式:分散的hadoop介绍Hadoop是Lucene......
  • 【linux】RAID磁盘阵列介绍
    文章目录RAID概念RAID分类raid0特点:RAID5RAID10RAID磁盘失效如何处理热备硬raid的介绍RAID概念RAID(RedundantArrayofIndependentDisks,独立磁盘冗余阵列)可以提供较普通磁盘更高的速度、安全性,所以服务器在安装时都会选择创建RAID。RAID的创建有两种方式:软RAID(通过操作系统软件......
  • Linux系统介绍
    什么是Linux?可以运行在PC机上类似于Unix风格的操作系统,由众多程序员通过Internet协作开发Linux是开源的开源好处:自由软件——使用自由、研究自由、散布自由、改良自由Linux系统结构:Linux操作系统由内核及应用程序组成。不同的厂商根据各自的需要将各种应用软件和Linux内核一起打包......
  • Vue3.0学习(一)------Vue简单介绍
    什么是Vue?官方原文:Vue是一款用于构建用户界面的JavaScript框架。它基于标准的HTML、CSS和JavaScript构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。简单来说,Vue就是一个构建用户界面的前端框架Vue的两个核心功能声明式渲染Vue基于标准HTML扩展了一......
  • 有名管道介绍及使用
    有名管道简介:匿名管道,由于没有名字只能用于亲缘关系的进程间通信。为了克服这个缺点,提出了有名管道(FIFO),也叫命名管道、FIFO文件。有名管道(FIFO)不同于匿名管道之处在于它提供了一个路径名与之关联,以FIFO的文件形式存在于文件系统中,并且其打开方式和打开一个普通文件是一样的。这......
  • HMI人机界面相关介绍及人机界面设计
    在工业自动化领域,HMI是人机界面的缩写。在工业中使用HMI来控制和监控机器。如果没有HMI,就很难在工业中拥有良好的自动化流程。人机界面的定义人机界面(HMI)是一种用户界面,允许人类操作员与机器或过程进行交互。HMI通常用于工业环境,允许操作员监视和控制过程,例如工厂或发电厂中......
  • C++/CLI 托管C++的数组介绍【4】
    Git源码地址 C++/CLI托管C++的托管与非托管字符串的相互转换【1】C++/CLI托管C++的数据类型介绍【2】C++/CLI托管C++的基本数据类型及函数【3】C++/CLI托管C++的数组介绍【4】C++/CLI托管C++之字符串封装【5】C++/CLI托管C++之enum枚举封装【6】C++/CLI托管C++之类、属性......