介绍

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

示例

假设有一个简单的分析器,它接收一个字符串,并迭代该字符串中由连字符(-)分隔的值:
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

混合类Mixins介绍的更多相关文章

  1. 11.mixins混合类

      一.混合类(mixins) 使用基于类的视图,最大的优势之一就创建可复用的代码 我们编写的非常类似的代码,可以抽象出来,将这部分代码放到mixin类系列中,然后作为父类提供子类继承使用 from ...

  2. Django-rest-framework 接口实现 rest_framework 中有已经定义好的 工具类 mixins generics viewsets

    rest_framework.mixins 请求业务 的 5 种实现 ​ mixin(混合类):不能单独使用,和其它类搭配起来使用(利用了Python支持多继承) rest_framework.mix ...

  3. oc-12-NSString 类简单介绍及用法

    // 11-[掌握]NSString 类简单介绍及用法 #import <Foundation/Foundation.h> int main(int argc, const char * ...

  4. 【Entity Framework】初级篇--ObjectContext、ObjectQuery、ObjectStateEntry、ObjectStateManager类的介绍

    本节,简单的介绍EF中的ObjectContext.ObjectQuery.ObjectStateEntry.ObjectStateManager这个几个比较重要的类,它们都位于System.Data ...

  5. Entity Framework 学习初级篇2--ObjectContext类的介绍

    转自:http://www.cnblogs.com/Tally/archive/2012/09/14/2685014.html 本节,简单的介绍EF中的ObjectContext.ObjectQuer ...

  6. js深入研究之扩展类,克隆对象,混合类(自定义的extend函数,clone函数,与augment函数)

    1.类扩展 /* EditInPlaceField类 */ /* 扩展函数 */ function extend(subClass, superClass) { var F = function() ...

  7. CImage类的介绍与使用

    CImage类的介绍与使用 程序代码下载处:http://download.csdn.net/source/2098910 下载处:http://hi.baidu.com/wangleitongxin ...

  8. Entity Framework 学习初级篇2--ObjectContext、ObjectQuery、ObjectStateEntry、ObjectStateManager类的介绍

    本节,简单的介绍EF中的ObjectContext.ObjectQuery.ObjectStateEntry.ObjectStateManager这个几个比较重要的类,它们都位于System.Data ...

  9. JdbcTemolate类的介绍<一>

    JdbcTemolate类的介绍 JdbcTemplate是Spring JDBC的核心类,封装了常见的JDBC的用法,同时尽量避免常见的错误.该类简化JDBC的操作,我们只需要书写提供SQL的代码和 ...

  10. 【转】Spring学习---Bean配置的三种方式(XML、注解、Java类)介绍与对比

    [原文]https://www.toutiao.com/i6594205115605844493/ Spring学习Bean配置的三种方式(XML.注解.Java类)介绍与对比 本文将详细介绍Spri ...

随机推荐

  1. [转帖]探索惊群 ④ - nginx - accept_mutex

    https://wenfh2020.com/2021/10/10/nginx-thundering-herd-accept-mutex/   由主进程创建的 listen socket,要被 fork ...

  2. [转帖]CentOS7完美升级gcc版本方法

    https://blog.whsir.com/post-4975.html 在某些应用场景中,需要特定的gcc版本支持,但是轻易不要去编译gcc.不要去编译gcc.不要去编译gcc,我这里推荐使用红帽 ...

  3. 金蝶Cosmic虚拟机简单使用与总结

    背景 知己知彼 简单学习下友商发出来的测试软件 看看有否对自己现在的工作有所指导 也看看对方的部署方式有啥优缺点 当然了仅是测试, 不是生产软件可能有失真. 注意 我没有测试序列号, 登录系统耗时很久 ...

  4. 【我在京东做研发】揭秘支撑京东万人规模技术人员协作的行云DevOps平台

    分享人:孙长虹 京东云DevOps解决方案架构师 复旦大学计算机系毕业,并拥有人民大学心理学硕士学位.曾任职于Alcatel-Lucent,IBM和惠普,具有丰富的大型复杂产品研发及项目管理经验,擅长 ...

  5. css伪类和伪元素在项目中的使用-红色*显示

    CSS使用伪类给表单添加星号 <style type="text/css"> .form-item label::before { content: '*'; colo ...

  6. vue中使用refs出现undefined的解决方法

    最近遇见一个情况, 在methods:{}中的某个方法, 通过父组件去调用子组件的一个方法:this.$refs.xxx 打印出来的却是undefined? 因为: 是如果在DOM结构中的某个DOM节 ...

  7. Qt "有效且启用的储存库"问题

    传送门 : https://www.cnblogs.com/SaveDictator/p/8532664.html 看就完了, 反正我好了 https://mirrors.tuna.tsinghua. ...

  8. 手撕Vue-实现计算属性

    前言 经过上一篇的学习, 完成了将数据代理到了 Nue 的实例上方,这个我们已经撕完了.接下来要实现的是计算属性,计算属性的实现原理是通过 Object.defineProperty() 来实现的,我 ...

  9. 安装 Nginx 修改默认端口

    用远程工具连接我们上次购买的机器,这里我要介绍一个知识点,博主使用的工具是 MobaXterm,这个工具有一个多操作的功能,在下图的位置可以开启多操作,然后连接你的服务器机子即可: 首先我们将机子里面 ...

  10. 事务提交之后再执行某些操作 → 引发对 TransactionSynchronizationManager 的探究

    开心一刻 昨晚,小妹跟我妈聊天 小妹:妈,跟你商量个事,我想换车,资助我点呀 妈:哎呀,你那分扣的攒一堆都够考清华的,还换车资助点,有车开就不错了 小妹:你要是这么逼我,别说哪天我去学人家傍大款啊 妈 ...