2014-07-14 82 views
1

我發現我能夠覆蓋諸如內置類的__iadd__方法__iadd__和其他經營者的行爲,但我不能重新分配__iadd__僅僅改變自己的行爲:動態變化

class OverrideList(list): 
    def __iadd__(self, x): 
     print("You'll see this") 
     return list.__iadd__(self, x) 

class ReassignList(list): 
    def iadd(self, x): 
     print("You'll never see this") 
     return list.__iadd__(self, x) 
    def __init__(self, *args, **kw): 
     list.__init__(self, *args, **kw) 
     self.__iadd__ = self.iadd 

ol = OverrideList() 
ol += range(3) 

rl = ReassignList() 
rl += range(3) 

有什麼我可以做的,會讓我ReassignList.iadd?

我最初以爲好笑的約IADD是,這是一個「插槽包裝」,而不是一個方法,但這個片段讓我懷疑:

class OverrideThenReassign(OverrideList): 
    def iadd(self, x): 
     print("You won't see this either") 
     return list.__iadd__(self, x) 
    def __init__(self, *args, **kw): 
     list.__init__(self, *args, **kw) 
     print("OverrideThenReassign.__iadd__ starts out as {} not as a slot wrapper".format(self.__iadd__.__class__)) 
     self.__iadd__ = self.iadd 

的動機概括爲writing a PersistentList subclass of list技術通過用代碼包裝方法來保存有問題的數據結構到磁盤。有草稿here。編輯:這個問題和this one差不多。這個問題被埋葬在一片飽滿的gobbledygook中,所以我不會把這個標記爲重複,除非一個SO超級巨星建議這樣做。

+0

我想你想使用[代理模式(HTTP: //en.wikipedia.org/wiki/Proxy_pattern)。 –

+0

將這些方法封裝在類級而不是各個實例上。 – user2357112

+0

正如其他答案所說 - 正如我在聊天中所說的 - 除了通過在子類上重新定義它們之外,您不能輕易覆蓋特殊方法。 Python不使用普通屬性查找系統來獲取特殊方法。 –

回答

0

這是基於@ user2357112的評論答案(「包裹方法在類級別,而不是單獨的實例」)

class ReassignList(list): 
    @staticmethod 
    def iadd(left, right): 
     print("Now this works!") 
     return list.__iadd__(left, right) 
    def __init__(self, *args, **kw): 
     list.__init__(self, *args, **kw) 
ReassignList.__iadd__ = ReassignList.iadd 
0

我有一個解決方案,您使用ProxyTypes(*從執行Proxy Pattern

#!/usr/bin/env python 


from __future__ import print_function 


from peak.util.proxies import ObjectWrapper 


class ListProxy(ObjectWrapper): 

    def __init__(self, obj): 
     super(ListProxy, self).__init__(obj) 

    def __iadd__(self, other): 
     print("You'll see this.") 
     return super(ListProxy, self).__iadd__(other) 


xs = ListProxy([1, 2, 3]) 
xs += [4, 5, 6] 

輸出爲我們節省了:

$ python -i foo.py 
You'll see this. 
>>> xs 
[1, 2, 3, 4, 5, 6] 
>>> 
0

這確實你需要什麼,而不另外下載:

class perpList(list): 
    def __init__(self, *args, **kwargs): 
     super(perpList, self).__init__(*args, **kwargs) 
    def __iadd__(self,x): 
     print "adding element {0}".format(x) 
     return super(perpList, self).__iadd__(x) 

a = perpList([1,2,3,4,5,6]) 
print a 
a += [19] 
print a 

輸出:

[1, 2, 3, 4, 5, 6] 
adding element [19] 
[1, 2, 3, 4, 5, 6, 19] 

代碼在repl.it上測試 - Python 2.7.2。

詹姆斯的解決方案有一個好處,你可以基本上只用一個類來代理任何東西,但增加了依賴性,並且(在我看來,只有少量的可讀性 - 因爲通過檢查你實際上並不明顯代理)。

+0

這與OverrideList有何不同? – kuzzooroo

+0

你有一點 - 所以 - 爲什麼不OverrideList做你想做的 - 你提出了兩次嘗試,我認爲你不能得到它的工作。既然你想要一個通用的解決方案子類列表 - 代理模式將工作。 –

+0

OverrideList的問題是我必須事先知道我想包裝哪些方法並分別處理它們。在我發佈的用例中,這是一個問題。 – kuzzooroo