返回顶部
首页 > 资讯 > 后端开发 > Python >一个例子走近 Python 的 Mixi
  • 711
分享到

一个例子走近 Python 的 Mixi

例子PythonMixi 2023-01-31 08:01:03 711人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

这篇博客,是我在看了《python GUI Programming with Tkinter》第 76 页的小节 Exploiting the power of multiple inheritance 之后,压抑不住自己的激动

这篇博客,是我在看了《python GUI Programming with Tkinter》第 76 页的小节 Exploiting the power of multiple inheritance 之后,压抑不住自己的激动兴奋之情,认真整理书写分享出来的。所用到的也是这一节作者写出来的代码,希望能给广大网友跟我一样的恍然大悟的痛快的感觉。

言归正传,Python 无疑是支持多继承的。我们可以利用 Python 的这种特性,实现一种叫做 Mixin 的类:

Mixin classes contain only a specific set of functionalities that we want to be able to mix in with other classes to compose a new class.(引用于 《Python GUI Programming with Tkinter》P76)

作者的这句话是什么意思呢?我大概翻译一下:

Mixin 类只包含了一组特定的函数集合,而我们将会将其与其他类进行混合,从而生成一个适用于实际需要的新类

看文本介绍太过于苍白,我们来看一个例子是最好的。

这里,我直接先上代码,有兴趣的同学,可以暂停到这里,看看这段代码中的 subclass.display() 这行代码,究竟是怎么执行的:

class Displayer():
    def display(self, message):
        print(message)


class LoggerMixin():
    def log(self, message, filename='logfile.txt'):
        with open(filename, 'a') as fh:
            fh.write(message)

    def display(self, message):
        super().display(message)
        self.log(message)


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")

代码不多,也就拢共 22 行,22 行的代码里面,定义了 3 个类。其中 MySubClass 多继承了 LoggerMixin 类和 Displayer 类。看似并没有什么异常的代码里面,当你尝试去仔细推敲 subclass.display() 的调用逻辑之后,就变得异常的复杂。

3 个类的作用

首先,我们先来依次介绍下这 3 个类的作用:

1. Displayer 类
只有一个函数,display 函数,其简单打印输出传进来的 message 字符串

2. LoggerMixin 类
这个类就是我们引言中提到的 Mixin 类,也就是说,这个类的方法,就是我们想要与 Displayer 类进行混合,然后生成我们想要的新类 MySubClass 的。

这个类有两个方法:

log 方法使用了 with open 语法操作了一个日志文件,日志文件缺省命名为 logfile.txt,然后将得到的 message 参数追加到这个文件中去。

display 方法调用了 super() 的 display 方法,然后调用了 self.log 方法。

这里问题就来了:我们的 Mixin 类根本就没有继承任何除了 Object 类之外的父类呀,也就是说,Object 类没有 display 方法,那么 LoggerMixin 类究竟是调用了谁的 display 方法呢?

这个问题相当诡异,我们之后再说。

3. MySubClass 类
这个类就是我们多继承而来的新类,只有一个方法,log 方法简单调用了父类的 log 方法。

提出问题

按照作者的原话来说:

Technically, LoggerMixin inherits from Python’s built-in object class, which has no display() method. How, then, can we call super().display() here?

这也是我在上一个标题中提出来的问题,我们的 LoggerMixin 类是怎么调用的 super().display() 方法的呢?

问题解释

作者很快就给出了答案:

In a multiple inheritance situation, super() does something a little more complex than just standing in for the superclass. It look up the chain of inheritance using something called the Method Resolution Order and determines the nearest class that defines the method we’re calling.

简单翻译下:

在多继承的环境下,super() 有相对来说更加复杂的含义。它会查看你的继承链,使用一种叫做 Methods Resolution Order(方法解析顺序) 的方式,来决定调用最近的继承父类的方法。

也就是说,我们的 MySubClass.display() 调用,触发了是这么一系列的行为:

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() 方法进行调用。

画图总结

为了方便大家理解,我画了一个简略的图方便理解:
一句简单的 subclass.display() 的背后,究竟发生了什么?

画图解释

看上面的解释或许还是觉得云里雾里,其实作者给出了更加简单的理解方式:

If this seems confusing, just remember that self.method() will look for method() in the current class first, then follow the list of inherited classes from left to right until the method is found. The super().method() will do the same, except that it skips the current class.

简单翻译下:

如果上述的解释太过于难以理解,我们可以简单记住,self.method() 将会先在当前类中查看 method() 方法,如果没有,就在继承链中进行查找,查找顺序就是你继承的顺序从左到右,直到 method() 方法被找到。super().method() 与 self.method() 是差不多的,只是 super().method() 需要跳过当前类而已。

这也就是我们的 Mixin 类牵扯出来的多继承函数调用问题的展现。

话说回来,为什么要叫做 Mixin 类呢?

Note that LoggerMixin is not usable on its own: it only works when combined with a class that has a display() method. This is why it’s a mixin class because it’s meant to be mixed in to enhance other classes.

也就是说,我们的 LoggerMixin 类是无法单独使用的,它必须要和一个拥有 display() 函数定义的类一起混合使用。这也就是为什么它被称作是 Mixin 类的原因,它总是需要与其他类混合来加强其他类。

至于这种编写代码模式的作用,还是有很大作用的。可以大大简化和方便我们的代码的开发过程。

阐述到这里,是不是也跟我一样有了恍然大悟的快感了呢?

Enjoy It:)

--结束END--

本文标题: 一个例子走近 Python 的 Mixi

本文链接: https://lsjlt.com/news/192745.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 一个例子走近 Python 的 Mixi
    这篇博客,是我在看了《Python GUI Programming with Tkinter》第 76 页的小节 Exploiting the power of multiple inheritance 之后,压抑不住自己的激动...
    99+
    2023-01-31
    例子 Python Mixi
  • 100 个 Python 小例子(练习题一)
    目录实例001:数字组合 实例002:“个税计算”实例003:完全平方数实例004:这天第几天实例005:三数排序实例006:斐波那契数列实例007:copy实例008:九九乘法表实...
    99+
    2024-04-02
  • 由一个例子到python的名字空间
    源自我的博客 python里面最核心的内容就是:名字空间(namespace) 例1 #!/usr/bin/env python # encoding: utf-8 def func1(): x = 1 prin...
    99+
    2023-01-31
    例子 名字 空间
  • Python入门二(一个有趣的画图例子)
    画一条可爱的python(蟒蛇):import turtle#引入库函数turtle(画图的小乌龟)def drawSnake(rad, angle, len, neckrad):    for i in range(len):     ...
    99+
    2023-01-31
    画图 入门 例子
  • python mock 的一些小例子
    1.假如我想要mock库中date对象,但是我只想mock today()这个方法,就是today()返回我想要的结果,但是其他的date的初始化方法不能有所改变。 from datatime import date with patc...
    99+
    2023-01-31
    些小 例子 python
  • js获取最近一周一个月三个月时间的示例分析
    js获取最近一周一个月三个月时间的示例分析,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。获取近一周时间var end = new D...
    99+
    2023-06-22
  • js获取最近一周一个月三个月时间的简单示例
    目录获取近一周时间获取近一个月时间获取近三个月时间New Date()与setDate()参数总结获取近一周时间 var end = new Date(); var year =...
    99+
    2024-04-02
  • oracle pro*c的一个简单例子
    一、环境 参见unbuntu下Docker安装oracle和mysql,sqlserver。 创建例子用到的视图: SQL> create view mysc as select sc.sno,sc.cno,sc.grad...
    99+
    2014-06-06
    oracle pro*c的一个简单例子
  • asp.net 组合模式的一个例子
    代码如下: using System; using System.Collections.Generic; using System.Linq; using System.T...
    99+
    2022-06-07
    net ASP.NET 组合模式 ASP
  • kettle modified javascript 步骤的一个例子
    例子里用到的 org.htmlparser.Parser 是一个html 的解析器,可以在 sourceforge 上下载。这个例子使用 org.htmlparser.Parser 包来解析一个 html 格式的字符串,要解析的 html ...
    99+
    2023-06-03
  • 最近找到了一个免费的python教程,两
    最近找到了一个免费的python教程,两周学会了python开发。推荐给大家,希望召集更多的朋友一起学习python。 小编有一个群 78486745 :里面有很多python爱好者讨论学习,有资料,想学python的可以一起加...
    99+
    2023-01-31
    找到了 教程 python
  • 一个oracle 完整创建 tablespace 的例子
    倒腾oracle 有段时间了。因为项目经常要用到,一些基础的功能还是需要把握的,方便平时项目的对接及维护,实事求是,上图说话,今天记录一个 oracle 11g 完整创建 tablespace 的...
    99+
    2024-04-02
  • opencv-python 基本例子3个
    其中的内容均参考自官网的说明: http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_tutorials.html 显示图片-Gui Features in OpenCV- Getti...
    99+
    2023-01-31
    例子 opencv python
  • 每天下班写一个python小例子,Day day up
    最近每天下班回家有时间就会写个小例子,一个月下来的成果,分享给大家学习共勉~第一个4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去掉不满足条件的排列...
    99+
    2023-06-02
  • 在Python使用yaml的几个例子
    python版本:2.7.5安装方法:pip install PyYaml“把变量写进yaml做配置文件,然后python脚本从yaml文件里面取到变量”的方法最近是在python编程里比较流行的配置项方法。yaml更加易读,而且通过缩进表...
    99+
    2023-01-31
    几个 例子 Python
  • 一个简单的eXosip的register注册例子
    以下是一个简单的eXosip库在C语言中实现注册的示例:```c#include <stdio.h>#include &...
    99+
    2023-09-08
    eXosip
  • JAVA数据库应用的一个小例子
    自己随便写的,以炉石为背景,写一个参考用的小例子,先上SQL表:if OBJECT_ID('card_pool') is not null drop table card_pool;create ...
    99+
    2024-04-02
  • hibernate第一个例子-保存对象
    3.hibernate第一个例子-保存对象使用hibernate框架需要导入的jar包:antlr-2.7.6backport-util-concurrentc3p0-0.9.1commons-collec...
    99+
    2024-04-02
  • Python 编写几个经典例子
    #九九乘法表 for i in range(1, 10): for j in range(1, i+1): print("%d*%d=%d\t" % (j, i, i*j), end="") ...
    99+
    2023-01-31
    几个 例子 经典
  • python学习(六)--正则的一些例子
    import re#正则表达式#compile函数,--将正则表达式转变为内部函数,提高执行效率strr = "python123456"pattern = "Python"res = re.compile(pattern)#当忽略匹配大小...
    99+
    2023-01-31
    正则 例子 python
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作