一些闲聊:

Mixin是一种设计模式、设计思想

并不是某个特定的class或者函数.

Java中的Mixin叫interface

Ruby中的Mixin叫Module

[2]优点:

1.mixin设计迷失可以在不对类的内容的修改前提下,扩展类的功能(添加父类)
2.更加方便的组织和维护不同的组建
3.可以根据开发需要任意调整功能
4.可以避免产生更多的类

缺点:
受继承关系限制,推荐只有两层的继承使用。

#-------------------------------------------------

案例一[3]:

class Role:def walk(self):print('走')#---------------------------------------------------------------
class RunMixin:def run(self):print('跑')class PromptSkillMixin:def use_prompt_skill(self):print('使用了一个瞬发技能')class WalkExMixin:#覆盖Role中的功能,因为下面是最先继承,Role是最后继承def walk(self):print('疾走')class RoleEx(WalkExMixin, PromptSkillMixin, RunMixin, Role):def marco(self):return [self.run, self.use_prompt_skill]def use_marco(self):print("---------------use_marco技术----------------")for action in self.marco():action()print("--------use_marco结束----------")
if __name__ == '__main__':r = RoleEx()r.use_marco()r.walk()

实验结果:

---------------use_marco技术----------------

使用了一个瞬发技能
--------use_marco结束------------------
疾走

这个案例显而易见的好处是:

你在不用修改Role的情况下扩展了很多功能.

因为有的时候,Role这个是由你的同事开发的,你没有修改的权限,你的同事仅仅给了你调用接口的权限,

或者说,为了免责和稳定,比如到时候出问题谁背锅啊,你不被公司允许修改原来的代码.

#------------------------------------------------

案例二[1]:

class Displayer():def display(self, message):print("--------②这里是Displayer.display函数---start-----")print("Displayer的self=",self)print(message)print("--------②这里是Displayer.display函数---end-----\n")class LoggerMixin():def log(self, message, filename='logfile.txt'):print("MySubClass self=",self)with open(filename, 'a') as fh:print("--------③这里是LoggerMixin.log函数---start-----")fh.write(message)print("--------③这里是LoggerMixin.log函数---end-----\n")def display(self, message):print("display的self=",self)#这里的self类指代的是MySubClass,并不是LoggerMixinprint("------①这里是LoggerMixin的display函数-start--\n")super().display(message)#会调用Displayer.display()函数self.log(message)print("------①这里是LoggerMixin的display函数-end--\n")class MySubClass(LoggerMixin, Displayer):def log(self, message):super().log(message, filename='subclasslog.txt')subclass = MySubClass()
subclass.display("This string will be shown and logged in subclasslog.txt")'''
1. MySubClass.display() is resolved to LoggerMixin.display().
MySubClass.display() 方法被解析为 LoggerMixin.display() 方法的调用。
这应该还是比较好理解的。因为对于 MySubClass 类来说,
在继承链上的两个父类,LoggerMixin 和 Displayer 来说,LoggerMixin 是最近的,因此调用它的 display() 方法。2. LoggerMixin.display() calls super().display(), which is resolved to Displayer.display().
LoggerMixin.display() 方法调用了 super().display(),这一行代码按照我们刚才的解释,查看 MySubClass 的继承链,
是应该调用 Displayer 类的 display() 方法的。这一步是相对来说比较难以理解的。让我们这么来理解它,当 LoggerMixin.display() 中调用了 super().display() 的时候,它会尝试去寻找属于当前类的继承链。而这个当前类是什么类呢?
不是 LoggerMixin 类,而是 MySubClass 类。MySubClass 类的继承连是 LoggerMixin,然后 Displayer。所以,我们就找到了 Displayer 的 display() 方法。3. It alse calls self.log(). Since self, in this case,
is a MySubClass instance, it resolves to MySubClass.log().
MySubClass.log() calls super().log(), which is resolved back to LoggerMixin.log().
别忘了,我们的 LoggerMixin 类还调用了 self.log() 方法。
这个看似好像要直接调用 LoggerMixin 的 log 方法,其实不然。LoggerMixin 的 display() 方法在当前语境中的 self,其实是 MySubClass 类的对象,
因此对于 MySubClass 类的对象,想要调用 log 方法,
是直接调用自己类中的 log 方法,也就是 MySubClass.log() 方法,而不是 LoggerMixin.log() 方法的。而又因为 MySubClass.log() 方法调用了 super().log() 方法,这才根据继承链寻找最近的父类,才找到了 LoggerMixin 类中的 log() 方法进行调用。

这个例子在网上非常有名,[1]中分析了这个例子的细节,细节我已经都复制到上方的代码中了.

核心思想和目标是(个人分析):

假如没有LoggerMixin,这个代码就剩下Displayer,所以整体代码的目标是:

不修改Displayer的情况下(这个非常重要),扩充Displayer的功能.

#---------------案例二[1]实验结果-感性分析-------------------------

实验结果如下:

display的self= <__main__.MySubClass object at 0x7f59388331d0>
------①这里是LoggerMixin的display函数-start--

--------②这里是Displayer.display函数---start-----
Displayer的self= <__main__.MySubClass object at 0x7f59388331d0>
This string will be shown and logged in subclasslog.txt
--------②这里是Displayer.display函数---end-----

MySubClass self= <__main__.MySubClass object at 0x7f59388331d0>
--------③这里是LoggerMixin.log函数---start-----
--------③这里是LoggerMixin.log函数---end-----

------①这里是LoggerMixin的display函数-end--

我们很直观地可以看出:

如果没有LoggerMixin,那么上述结果就会只剩下红色部分,

当前实验结果的黑色部分是对原有的Displayer的类的功能进行扩充.

同时又确保Displayer的类不被修改

#----------------总结------------------------

个人总结MIXIN的作用:

不修改父类的情况下,对父类的功能进行扩增和删改

为什么没有"査"呢?像数据库那样的增删改查.

遗产项目中,同事给你的接口肯定是已经实现"查询和获取成员变量"的功能的,即使没有MIXIN也已经具备了"査"功能.

扩增:上面两个例子都体现了增加功能的作用

删改:参考上面的案例一,WalkExMixin中的Walk函数屏蔽了原始父类Role的Walk函数

所以说,MIXIN这种设计模式出现的目的就是:

可以对原始父类实现功能上的扩增和(删改).

#----------------------------------------

Reference:

[1]一个例子走近 Python 的 Mixin 类:利用 Python 多继承的魔力

[2]面向对象-mixin设计模式的应用(多继承应用场景)

[3]python_Mixin设计模式

Python中的Mixin详解相关推荐

  1. python的抽象类详解_第7.19节 Python中的抽象类详解:abstractmethod、abc与真实子类...

    第7.19节 Python中的抽象类详解:abstractmethod.abc与真实子类 一. 引言 前面相关的章节已经介绍过,Python中定义某种类型是以实现了该类型对应的协议为标准的,而不是以继 ...

  2. 【 Python 中 int 用法详解】(转载)

    Python 中 int 用法详解 欢迎转载,转载请注明出处! 文章目录 Python 中 int 用法详解 0. 参考资料 1. int 的无参数调用 2. int 接收数字作为参数 3. int ...

  3. Python 中 int 用法详解

    Python 中 int 用法详解 欢迎转载,转载请注明出处! 文章目录 Python 中 int 用法详解 0. 参考资料 1. int 的无参数调用 2. int 接收数字作为参数 3. int ...

  4. Python中self用法详解

    Python中self用法详解 https://blog.csdn.net/CLHugh/article/details/75000104 首页 博客 学院 下载 图文课 论坛 APP 问答 商城 V ...

  5. python中的字符串详解(附实现文字跑马灯效果)

    python中的字符串详解 1.什么是字符串 ​ 相信大家对字符串应该是再熟悉不过了吧,因为日常生活中的一句话,或是路边的一则广告,其实它都相当于一个字符串,而顾名思义,字符串也就是一串串的由零个或多 ...

  6. python中的GIL详解

    python中的GIL详解 参考Python-- GIL 锁简述 GIL是什么 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就 ...

  7. Python 中 with 用法详解

    浅谈 Python 的 with 语句:https://developer.ibm.com/zh/articles/os-cn-pythonwith/ python3,浅谈with的神奇魔法:http ...

  8. python中new方法详解及_Python中new方法的详解

    new_ 方法是什么? __new__方法其实就是创建对象的方法 new()方法是在类准备将自身实例化时调用. 一个类可以有多个位置参数和多个命名参数,而在实例化开始之后,在调用 init()方法之前 ...

  9. python中logging模块详解_python logging日志模块详解

    logging 日志模块详解 用Python写代码的时候,在想看的地方写个print xx 就能在控制台上显示打印信息,这样子就能知道它是什么了,但是当我需要看大量的地方或者在一个文件中查看的时候,这 ...

最新文章

  1. JVM源码分析之FinalReference完全解读
  2. SQL取xml中节点值
  3. 大学python实训总结-千锋Python实训总结 学好基础才能走的更远
  4. 4、linux网络编程--套接字的介绍
  5. 使用Myeclipse实现快速调试
  6. linux 生成字母序列,Python序列之字符串
  7. 音视频技术开发周刊 72期
  8. mysql 时间函数多了8小时_MySQL时间函数了解
  9. 静态网页托管_求职季,教你制作一份精美的在线网页简历,程序员必看!!
  10. jdk、cglib动态代理代码示例
  11. es6语法图片切换demo
  12. HDU 5183 Negative and Positive (NP) (hashmap+YY)
  13. turbo c 混编 汇编语言,浅谈Turbo C过程调用汇编
  14. matlab差值报错,matlab插值介绍
  15. 联想微型计算机B3O5,联想B3一体电脑
  16. python中pass语句的出现是为了保持程序结构的完整性_Python 为什么要有 pass 语句?...
  17. WinPE环境下WinNTSetup使用说明(WIM_ESD系统如何安装)
  18. 学术论文中常见的英文简写
  19. hp-ux系统备份与恢复常用命令
  20. jQuery-入口函数

热门文章

  1. C#类型与SQLSEVER类型对比
  2. MySql 事务+异常处理+异常抛出
  3. 学习scorllview
  4. 一个图片展示效果的站点
  5. 如何进行职业生涯规划
  6. 用闭包实现重载的过程学习闭包
  7. ++ 优化 频繁new_Java性能优化的50个细节,我必须分享给你!
  8. WEB前端 实现图片懒加载 echo.js
  9. cmder上传文件到服务器,wget 结合everything上传文件到服务器端(以及更改ip地址)...
  10. MD5加密解密简介和应用