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__返回的元組的元素順序不一樣會導致繼承的順序不一樣,類會優先繼承元組左邊的類


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM