2015-02-10 25 views
0

我有一個Python對象,我想屏蔽任何內部和外部訪問,並通過代理運行每個請求。我使用this到目前爲止工作正常的一段代碼。我將它分類並用我想要代理的對象初始化它。Python中的代理變量

不幸的是,它並沒有涵蓋從代理對象內部進行訪問的情況。

class A(object): 
    def do_something(self): 
     self.foo.perform_action() 

class MyProxy(Proxy):  
    def __init__(self, obj): 
     super(MyProxy, self).__init__(obj) 
     self.proxy_foo = ProxyFoo(obj.foo) 

    def __getattribute__(self, item): 
     if item == 'foo': 
      return self.proxy_foo 
     return super(MyProxy, self).__getattribute__(item) 

a = A() 
myproxy = Proxy(a) 
# do_something should work on proxy_foo, but it operates on a.foo 
myproxy.do_something() 

我該怎麼做才能改變這種情況?

+0

您是否爲代理覆蓋__setattr__? – 2015-02-10 04:50:01

+0

沒有。但在我的實際例子中,這個調用更像'self.foo.do_something_else()'。我在'__getattribute__'中有一個斷點,但它在返回'proxy_foo'的條件下從未真正停止過。 – orange 2015-02-10 04:52:16

+1

你的'代理'類是如何定義的? – 2015-02-10 04:56:52

回答

0

我不認爲這是一個好主意。我能想到的唯一方法是獲取do_something的訪問權限,並返回一個修改後的綁定方法與不同的self對象。這最多隻會造成混淆,最壞的情況是破壞,因爲這意味着當A嘗試訪問自己時,它不會真正訪問自己,而是代理。您可以與您現有的代理類做到這一點,但你必須要攔截訪問do_something,不foo

class MyProxy(Proxy):  
    def __init__(self, obj): 
     super(MyProxy, self).__init__(obj) 
     self.proxy_foo = 999 

    def __getattribute__(self, item): 
     #print("__getattribute__({}, {})".format(self, item)) 
     if item == 'foo': 
      return self.proxy_foo 
     if item == 'do_something': 
      return functools.partial(object.__getattribute__(self, '_obj').__class__.do_something, self) 
     return super(MyProxy, self).__getattribute__(item) 

a = A() 
myproxy = MyProxy(a) 

然後:

>>> myproxy.do_something() 
999 

這種方法只適用於所有因爲Proxy類甚至代理的__class__屬性,導致代理僞裝成代理類的實例。即使如此,這意味着myproxy.do_something()會導致對__getattribute__進行四次單獨調用,您可以看到是否取消註釋該打印(其中一個獲得do_something__class__的內部生成查找,一個獲得foo,另一個獲得proxy_foo)。你可以看到,如果你正在調用一個實際上對任何屬性做任何事情的方法,調用次數可能會迅速增長。此外,我不清楚它甚至可以適用於所有情況(例如,類方法,雙下劃線私有類級變量)。甚至可以想象,它會進入無限循環的角落情況。

一般而言,代理是爲了提供一種方法,在一些利用該對象的封閉操作中用一個對象替換另一個對象。試圖欺騙一個對象相信它本身就是一個其他的對象是一個冒險的命題。你可能更適合製作一個mixin代理類,它有自己的__getattribute__做你想要的代理,然後製作一個與A混合並使用A的實例而不是A的實例的子類。這取決於你是什麼試圖用這個代理來實現。

+0

再次感謝您的見解。正如我已經提到的,我可能會用另一種不那麼令人困惑的設計。 – orange 2015-02-10 07:21:25