1. Mix-in技术介绍
Mixin可以译为混入,就是在不改变原对象的情况下对其进行扩展。本文介绍了在 Python 语言中,如何实现Mixin技术,及安装的相应技巧。

1.1. 什么是Mix-in技术
Mix- in技术,中文不知道应该如何称呼,但意思好象是混入。它的作用是,在运行期间,动态改变类的基类或类的方法,从而使得类的表现可以发生变化。可以用在一 个通用类接口中,根据不同的选择使用不同的低层类实现,而高层类不用发生变化。而且这一实现可以在运行过程中动态进行改变。由于我也是刚看到,大家有问题 可以与我进行交流。这就是我看到的文章的链接。

1.2. 基类的增加
有一个类,

class foo:
    pass
我可以定义另外一个类,

class foobase:
    def hello(self):
        print "hello"
如果我直接调用:

>>> obj=foo()
>>> obj.hello()
这时你会看到出错。那么我可以这样:

>>> foo.__bases__ +=(foobase,)
>>> obj.hello()
hello
成功了。原理是,每个类都有一个bases属性,它是一个tuple,用来存放所有的基类。而且在运行中,可以动态改变。所以当我们向其中增加新的基类时,再次调用原来不存在的函数,由于基类中的函数已经存在了,所以这次成功了。

这是一个最简单的应用,可以看到我们可以动态改变类的基类。有几个注意事项要说一下:

__bases__是一个tuple,所以增加一个值要使用tuple类型,而单个元素tuple的写法为(foobase,)

类必须先存在。所以,如果想使用这一技术,先要将相关的类的模块导入(import)。
由于Mix-in是一种动态技术,以多继承,对象为基础,而python正好是这样的语言,使得在python中实现这一技术非常容易。

1.3. 函数替换
在前面,简单地向大家介绍了一下Mix-in技术,它实现了基类的动态增加。这样我们就可以在运行时,根据选择可以动态地增加基类,从而实现不同的目的。现在还有一个问题,就是,在基类与派生类中都有同名的函数,要如何处理呢?

在Python中,如果派生类中有与基类同名的函数,那么调用函数时,会调用派生类的函数,而不是基类的函数,可以测试一下:

>>> class foobase:
        def a(self):
                print "hello"

>>> class foo(foobase):
        def a(self):
                print "foo"

>>> c=foo()
>>> c.a()
foo
可以看出,执行的是foo类的函数。这样在使用Mix-in技术时,如果原来的类中存在与Mix类中同名的函数,那么Mix类中的函数不会运行,如果想对其进行替换怎么办呢?方法就是使用getattr()和setattr()函数。当然还是最简单的。

定义两个类:

>>> class foobase:
        def a(self):
                print "hello"

>>> class foo:
        def a(self):
                print "foo"

>>> f=getattr(foobase, "a")
>>> setattr(foo, "a", f.im_func)     #f.im_func会得到真正的函数对象
>>> c=foo()
>>> c.a()
hello
可以看到,函数被替换了。

注意,使用dir(f)还会看到其它的属性im_class,它表示这个函数属于哪个类,im_self表示属于哪个实例。

1.4. Mix-in安装函数
前面讲了基本的实现技术,下面给大家介绍一个Mix-in安装函数,这个函数是从前面所说的文章copy下来的。

import types

def MixIn(pyClass, mixInClass, makeAncestor=0):
   if makeAncestor:
     if mixInClass not in pyClass.__bases__:
        pyClass.__bases__ = (mixInClass,) + pyClass.__bases__
   else:
     # Recursively traverse the mix-in ancestor
     # classes in order to support inheritance
     baseClasses = list(mixInClass.__bases__)
     baseClasses.reverse()
     for baseClass in baseClasses:
        MixIn(pyClass, baseClass)

# Install the mix-in methods into the class
     for name in dir(mixInClass):
        if not name.startswith('__'):
        # skip private members
           member = getattr(mixInClass, name)
           if type(member) is types.MethodType:
               member = member.im_func
           setattr(pyClass, name, member)
这 个函数可以将某个mix-in类安装为指定类的基类,同时可以通过关键字参数指定在基类中的顺序,是最前还是最后。因为Python在处理基类时,是安顺 序进行的,所以安装在最前则优先级最高。同时对于指定类的方法如果在mix-in类中存在,则将指定类中的方法替换成mix-in类中的方法。

if makeAncestor:
     if mixInClass not in pyClass.__bases__:
        pyClass.__bases__ = (mixInClass,) + pyClass.__bases__
如果makeAncestor为1,表示是安装在最前,则首先判断在pyClass的基类中是否存在mixInClass类,如果不存在,再进行安装。

else:
     # Recursively traverse the mix-in ancestor
     # classes in order to support inheritance
     baseClasses = list(mixInClass.__bases__)
     baseClasses.reverse()
     for baseClass in baseClasses:
        MixIn(pyClass, baseClass)
如 果makeAncestor为0,并不将mixInClass安装在最后,原作者说他在实际中没有这样用的。那么它完成什么任务呢?它实际完成了一个递 归,即从mixInClass的最底层的基类开始(因为mixInClass也可能是多重继承而来的),对pyClass中也存在的函数进行替换。这样执 行完毕后,mixInClass类中,包含所有基类中的函数,如果有与pyClass类中的函数重名的,都将pyClass中的函数替换成 mixInClass相应的函数。(有些复杂!)

# Install the mix-in methods into the class
     for name in dir(mixInClass):
        if not name.startswith('__'):
        # skip private members
           member = getattr(mixInClass, name)
           if type(member) is types.MethodType:
               member = member.im_func
           setattr(pyClass, name, member)
这 步完成重名函数的替换。首先去掉私有方法(私有方法名前有'__').得到mixInClass类中的指定名字的方法对象,判断是否为方法类型。因为还有 可能取到属性。在types模块中包含了一些类型,可以用它来判断是否为方法类型。对于方法对象,如果是类方法,实际的函数应使用它的属性 im_func。然后将pyClass相应的方法替换成mixInClass中的方法。

这样就将mixInClass安装为pyClass的基类了。

使用例子如:

from classa import classa
from classb import classb
MixIn(classa, classb) #将classb安装为classa的基类

转载于:https://www.cnblogs.com/huazi/archive/2012/05/09/2492041.html

Python Mixin技术介绍相关推荐

  1. python软件界面-python软件界面介绍(python软件介绍)

    python软件界面介绍 1.接口初始化 当我们使用pycharm工具时,我们将遇到的第一个问题是,在进行各种配置后界面变得混乱时,我们该怎么办?我们应该还原,那么如何还原初始设置? 尽管此工具是从e ...

  2. python url模块介绍_python 中 urlparse 模块介绍

    urlparse模块主要是用于解析url中的参数  对url按照一定格式进行 拆分或拼接 1.urlparse.urlparse 将url分为6个部分,返回一个包含6个字符串项目的元组:协议.位置.路 ...

  3. 7套干货,Python常用技术学习知识图谱!!(史上最全,建议收藏)

    大家好,我是明月十四桥! 你要偷偷努力,然后惊艳所有人~ 给大家推荐 7 个宝藏级教程,视频课是永久有效的,可以随时学习,有几门课程还有CSDN官方学习答疑群,课程右边扫码入群,讲师在群里答疑哈~ 目 ...

  4. Python开发技术详解PDF

    Python开发技术详解(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1F5J9mFfHKgwhkC5KuPd0Pw 提取码:xxy3 复制这段内容后打开百度网盘手 ...

  5. 《Getting Started with WebRTC》第二章 WebRTC技术介绍

    <Getting Started with WebRTC>第二章 WebRTC技术介绍 本章作WebRTC的技术介绍,主要讲下面的概念:   .  怎样建立P2P的通信   .  有效的信 ...

  6. Python实战技术 - Python虚拟隔离环境 和 Docker技术

    Python实战技术 - Python虚拟隔离环境 和 Docker技术 已经学过,只想查查手册?--试试直接跳转到命令: (1)使用venv创建相关命令 (2)使用virtualenv创建相关命令 ...

  7. 容器技术介绍之docker核心技术概述

    容器简单来说是一种沙盒技术,将应用"装"进沙盒中,像集装箱一样,把应用封装起来,使得应用之间不会相互干扰,而放进沙盒中的应用也方便"搬家".本文基于docker ...

  8. Frida-Dexdump 脱壳工具下载使用以及相关技术介绍

    Frida-Dexdump 脱壳工具下载使用以及相关技术介绍 文章目录 Frida-Dexdump 脱壳工具下载使用以及相关技术介绍 前言 一.查壳.反编译.APK工具推荐 二.查壳 1.方式1 2. ...

  9. Python+爬虫技术获取斗鱼直播图片(整理)

    核心内容: 1.爬虫的基本原理 2.利用Python爬取数据的方法(使用urllib爬取数据) 3.从斗鱼直播平台爬取图片 最近因为工作的原因,要利用爬虫的相关技术,获取html网页相关的数据,特意总 ...

最新文章

  1. iOS中你可能没有完全弄清楚的(一)synthesize
  2. Verilog中的二维数组及其初始化
  3. Windows 2000和WindowsXP中神秘的数字签名
  4. Uva12716 素数筛思想的应用
  5. 【MFC】带组合框的工具栏
  6. 从用户观点对计算机如何分类,从用户的观点看操作系统是
  7. me)不支持html,属于me的vue练习(参考菜鸟教程).html
  8. pcm 8k单声道和双声道采样_音频接口PCM
  9. 第7章-选择器+伪类
  10. 【关键词提取】第二篇:数据集、实现代码介绍
  11. linux 添加新用户时常用的操作
  12. [Share]前端开发大众手册(包括工具、网址、经验等)
  13. 少走弯路,给3~5年java程序员的唯一一条建议
  14. 步进电机和伺服电机的区别
  15. 基于国密算法SM2非证书标识公钥密码技术(IPK)
  16. 众泰Z700导航升级高德地图
  17. DAY1(02-HTML标签(上))
  18. 亚信卸载-无需密码卸载
  19. Java程序员必看的15本书的电子版下载地址
  20. LANDesk准入认证客户端 每次启动都丢失

热门文章

  1. requireJS对文件合并与压缩(二)
  2. 在HTML网页中嵌入脚本的方式
  3. js数组的定义方法与基本使用
  4. 学习NodeJS第一天:node.js引言
  5. C#2.0 从sql server 中读取二进制图片
  6. CentOS 更改Apache默认网站目录
  7. 云计算设计模式(十六)——优先级队列模式
  8. Action和Func的区别
  9. Windows上的单个进程所能访问的最大内存量是多少?它与系统的最大虚拟内存一样吗?这对于系统设计有什么影响?...
  10. poj-2828 Buy Tickets ***