zoukankan      html  css  js  c++  java
  • python用法——Mixin

    在读werkzeugflask的源码中,经常能遇到类名中有mixin这个东西。这个东西的用法让我想到了java中的接口名有able的用法。今天我就来看了看这个mixin是什么东西。
    学习了python的都知道,python是支持多继承的,但是支不支持动态继承性质呢?在程序运行过程中,重定义类的继承,python是支持这种动态继承性质的。这也就是python中的mixin,在定义类过程中改变类的继承顺序,继承类。当某个模块不能修改时,通过mixin方式可以动态添加该类的方法,动态改变类的原有继承体系

    Mixin

    Mixin编程是一种开发模式,是一种将多个类中的功能单元的进行组合的利用的方式,这听起来就像是有类的继承机制就可以实现,然而这与传统的类继承有所不同。通常mixin并不作为任何类的基类,也不关心与什么类一起使用,而是在运行时动态的同其他零散的类一起组合使用
    使用mixin机制有如下好处:可以在不修改任何源代码的情况下,对已有类进行扩展;可以保证组件的划分;可以根据需要,使用已有的功能进行组合,来实现“新”类;很好的避免了类继承的局限性,因为新的业务需要可能就需要创建新的子类。
    在举例子之前,我们需要先熟悉几个关键字:

    1. __bases__: 返回一个元组,该元组元素是类的基类,如:

      class a:
      pass

      print(a.bases)
      (<class 'object'>,)
      可见a类继承了object

    2. __mro__: This attribute is a tuple of classes that are considered when looking for base classes during method resolution. 我的理解是 返回一个元组,该元组元素是该类的继承的类,当查询继承的时候会按从左到右的顺序。以刚刚的a类为例:

      print(a.mro)
      (<class 'main.a'>, <class 'object'>)

    例子

    在了解了以上的知识后,我来举个例子

    import types
    
    def mixin(pyClass, pyMixinClass, key=0):
        if key:
            pyClass.__bases__ = (pyMixinClass,) + pyClass.__bases__
        elif pyMixinClass not in pyClass.__bases__:
            pyClass.__bases__ += (pyMixinClass,)
        else:
            pass
    
    class test1:
        def test(self):
            print('In the test1 class!')
    
    class testMixin:
        def test(self):
            print('In the testMixin class!')
    
    class test2(test1, testMixin):
        def test(self):
            print('In the test2 class!')
    
    class test0(test1):
        pass
    
    if __name__ == '__main__':
        print(test0.__mro__)  #继承了test1,object
        test_0 = test0()
        test_0.test()  #调用test1的方法
        mixin(test0, testMixin, 1)  #优先继承testMixin类
        test__0 = test0()
        test__0.test()  #由于优先继承了testMixin类,所以调用testMixin类的方法
        print(test0.__mro__)
    
        print(test2.__mro__)
        mixin(test2, testMixin)
        print(test2.__mro__)
    

    输出结果:

    (<class '__main__.test0'>, <class '__main__.test1'>, <class 'object'>)
    In the test1 class!
    In the testMixin class!
    (<class '__main__.test0'>, <class '__main__.testMixin'>, <class '__main__.test1'>, <class 'object'>)
    (<class '__main__.test2'>, <class '__main__.test1'>, <class '__main__.testMixin'>, <class 'object'>)
    (<class '__main__.test2'>, <class '__main__.test1'>, <class '__main__.testMixin'>, <class 'object'>)
    

    注意本例的mixin方法,它的作用就是动态地给某个类(pyClass)通过继承的方式添加方法。
    要注意:pyClass.__bases__ = (pyMixinClass,) + pyClass.__bases__pyClass.__bases__ += (pyMixinClass,) 二者的顺序是不一样的。 还是用例子说明:

    a = (1,)
    a = a + (2,)
    print(a)
    #输出:(1,2)
    a = (3,) + a
    print(a)
    #输出:(3,1,2)
    

    __bases__返回的元组的元素顺序不一样会导致继承的顺序不一样,类会优先继承元组左边的类

  • 相关阅读:
    LintCode-35.翻转链表
    LintCode-159.寻找旋转排序数组中的最小值
    LintCode-73.前序遍历和中序遍历树构造二叉树
    LintCode-9.Fizz Buzz 问题
    NOI 2018 归程 (Kruskal重构树)
    模板 NTT 快速数论变换
    模板 FFT 快速傅里叶变换
    BZOJ 3510 首都 (LCT)
    BZOJ 4530 [BJOI2014]大融合 (LCT)
    BZOJ 3282 Link Cut Tree (LCT)
  • 原文地址:https://www.cnblogs.com/eric-nirnava/p/mixin.html
Copyright © 2011-2022 走看看