Python对象代理:如何访问代理

时间:2013-07-11 02:40:00

标签: python proxy-classes

我找到了this配方来创建代理类。我用它来包装自定义对象,并希望重载某些属性,并将新属性附加到代理。但是,当我在代理上调用任何方法时(从代理类中),我最终被委托给了我不想要的包装。

有没有办法访问或存储对代理的引用?

这是一些用于演示问题的代码(未经测试)。

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)

现在似乎可以解决这个问题,但最好将其直接添加到Proxy类。

1 个答案:

答案 0 :(得分:1)

您的代码出错的原因是__getattribute__中的循环。您希望覆盖__getattribute__,以便可以在代理类本身中访问某些属性。但是,让我们看看。

当您致电p.value时,系统会调用__getattribute__。然后它来到这里if attr == 'value': return self.another_value()。在这里,我们需要致电another_value,以便我们再次输入__getattribute__

这次我们来return super(MyObjectProxy, self).__getattribute__(attr)。我们致电Proxy的{​​{1}},并尝试在__getattribute__中抓取another_value。所以例外发生了。

您可以从追溯中看到我们最终会转到不应该去的Myobject

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()