2013-07-11 38 views
3

我發現this recipe創建一個代理類。我用它來包裝自定義對象,並且想要重載某些屬性並將新屬性附加到代理上。然而,當我在代理上調用任何方法時(從代理類中),我最終被委託給了不是我想要的包裝。Python對象代理:如何訪問代理

有什麼方法可以訪問或存儲對代理的引用嗎?

下面是一些代碼(未經測試)來演示問題。

class MyObject(object): 
    @property 
    def value(self): 
    return 42 

class MyObjectProxy(Proxy): # see the link above 
    def __getattribute__(self, attr): 
    # the problem is that `self` refers to the proxied 
    # object and thus this throws an AttributeError. How 
    # can I reference MyObjectProxy.another_value()? 
    if attr == 'value': return self.another_value() # return method or attribute, doesn't matter (same effect) 
    return super(MyObjectProxy, self).__getattribute__(attr) 

    def another_value(self): 
    return 21 

o = MyObject() 
p = MyObjectProxy(o) 
print o.value 
print p.value 

從某種意義上說我的問題是,代理工作太出色了,隱藏所有自己的方法/屬性,並冒充自己作爲代理對象(這是它應該做的)...

更新

基於下面的評論,我改變__getattribute__這樣:

def __getattribute__(self, attr): 
    try: 
     return object.__getattribute__(self, attr) 
    except AttributeError: 
     return super(MyObjectProxy, self).__getattribute__(attr) 

這看ms現在就可以完成這個技巧,但最好直接添加到Proxy類中。

回答

0

你的代碼出錯的原因是循環__getattribute__。您想覆蓋__getattribute__,以便您可以在代理類本身中達到某些屬性。但讓我們看看。

當您致電p.value時,__getattribute__被調用。然後它來到這裏if attr == 'value': return self.another_value()。這裏我們需要撥打another_value,所以我們再次輸入__getattribute__

這次我們來到這裏return super(MyObjectProxy, self).__getattribute__(attr)。我們稱之爲Proxy__getattribute__,它試圖在Myobject中獲取another_value。所以例外發生。

你可以從追蹤中看到我們終於去了return super(MyObjectProxy, self).__getattribute__(attr)不該去的地方。

Traceback (most recent call last): 
    File "proxytest.py", line 22, in <module> 
    print p.value 
    File "proxytest.py", line 13, in __getattribute__ 
    if attr == 'value': return self.another_value() # return method or attribute, doesn't matter (same effect) 
    File "proxytest.py", line 14, in __getattribute__ 
    return super(MyObjectProxy, self).__getattribute__(attr) 
    File "/home/hugh/m/tspace/proxy.py", line 10, in __getattribute__ 
    return getattr(object.__getattribute__(self, "_obj"), name) 
AttributeError: 'MyObject' object has no attribute 'another_value' 

編輯:
變化的代碼if attr == 'value': return self.another_value()行至if attr == 'value': return object.__getattribute__(self, 'another_value')()

+0

感謝您的再現和確認,@張揚餘。有關如何獲得所需行爲的任​​何建議? – orange

+0

我已經更新了我的答案。請檢查。 @orange – zhangyangyu

+0

我以爲我曾嘗試過,但我一定犯了一個錯誤。你的解決方案工作正常在查看代理人的代碼之前,我先看看如何修改代理類來查找自己的屬性。 – orange