2015-09-25 59 views
0

在Python中,我使用了一個框架,讓我掛接到一個生命週期,像這樣:python mixin的方法不能被覆蓋(默認)?

class MyView(BaseView): 
    def pre_save(self): 
     print "view presave" 

我想寫一個mixin做一些pre_save,但我已經有很多的代碼在大量的類如上所述使用pre_save,而不呼叫super()。如果我這樣加入我的mixin:

class MyMixin(object): 
    def pre_save(self): 
     print "mixin presave" 

class MyView(MyMixin, BaseView): 
    def pre_save(self): 
     print "view presave" 

它自然地覆蓋mixin,並僅打印「查看預置」。有沒有另外一種偷偷摸摸的方式,我可以寫MyMixin以不強制所有的客戶意見記得打電話給super()

+1

不,沒有別的方法,只能從所有'pre_save()'方法中調用'super()'。如果存在'BaseView.pre_save()'(並且什麼也不做,甚至不調用'super()'),那麼隨處使用'super()'(mixin,具體視圖)將確保所有調用都被正確鏈接。 –

+0

在平凡的編程錯誤上打樁「偷偷摸摸的方式」只會增加一些應該修復的問題。修正你的觀點,以便他們正確地發出'超級'通話,從長遠來看,它將爲你節省更多的時間。 –

+0

@brunodesthuilliers我不認爲「純粹的編程錯誤」是準確的 - 以前沒有混入,因此不需要調用super(),也不需要知道如何實現mixin以利用它。就這樣,你可以不知不覺地在沒有警告的情況下刪除你的mixin的實現。 –

回答

1

這個答案是一個概念證明,而不是一個建議。 請勿在生產代碼中執行此操作。您將創建維護噩夢。我同意那些評論你的問題,即唯一安全的方法是編輯派生類。

也就是說,技術上可以使用metaclass

def do_evil(self, method): 
    print "doing evil" 
    MyMixin.pre_save(self) 
    method(self) 

class ConcentratedEvil(type): 
    tainted_classes = ['MyView'] # Add others as needed 
    def __new__(mcs, name, bases, dict): 
     if name in mcs.tainted_classes: 
      print "tainting {0} with the power of evil".format(name) 
      old_method = dict['pre_save'] 
      dict['pre_save'] = lambda x: do_evil(x, old_method) 
      print dict.keys() 
     return type.__new__(mcs, name, bases, dict) 

class BaseView(object): 
    pass 

class MyMixin(object): 
    __metaclass__ = ConcentratedEvil 
    def pre_save(self): 
     print "mixin presave" 

class MyView(MyMixin, BaseView): 
    def pre_save(self): 
     print "view presave" 

此時你可以這樣做:

>>> view = MyView() 
>>> view.pre_save() 
doing evil 
mixin presave 
view presave 
>>> 

我認爲這僅僅在進行MyMixin是在基類列表的前面。

+0

Neato。想想我可以自動地污染所有使用'MyMixin'的類,而不是維護'tainted_classes'列表? –

+0

嗯。大概。我敢打賭,你可以搜索「MyMixin」的基礎列表。我不確定如果你的課程在不同的模塊中它將如何工作。您可能需要檢查合格和不合格的名稱。 –