Python Mixin技术介绍
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技术介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: MEF学习笔记(6):出口和元数据
 - 下一篇: C语言实现简单线程池