Domanda

I found this recipe to create a proxy class. I've used it to wrap a custom object and would like to overload certain properties and also attach new attributes to the proxy. However, when I call any method on the proxy (from within the proxy class), I end up being delegated to the wrappee which is not what I want.

Is there any way of accessing or storing a reference to the proxy?

Here's some code (untested) to demonstrate the problem.

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

In a sense my problem is that the proxy works too good, hiding all its own methods/attributes and posing itself as the proxied object (which is what it should do)...

Update

Based on the comments below, I changed __getattribute__ to this:

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

This seems to do the trick for now, but it would be better to add this directly to the Proxy class.

È stato utile?

Soluzione

The reason that your code goes wrong is the loop in __getattribute__. You want to override __getattribute__ so you can reach certain properties in the proxy class itself. But let's see.

When you call p.value the __getattribute__ is called. Then it comes here if attr == 'value': return self.another_value(). Here we need to call another_value so we enter __getattribute__ again.

This time we comes here return super(MyObjectProxy, self).__getattribute__(attr). We call the Proxy's __getattribute__, and it tries to fetch another_value in Myobject. So the exceptions occur.

You can see from the traceback that we finally goes to return super(MyObjectProxy, self).__getattribute__(attr) that should not go to.

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'

edit:
Change the line of code if attr == 'value': return self.another_value() to if attr == 'value': return object.__getattribute__(self, 'another_value')().

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top