transparent proxy object

Irmen de Jong irmen at
Wed Feb 26 23:41:09 CET 2003

Alex A. Naanou wrote:
> Task:
>   "transparently" intercept/cache all calls to the object, all its
> attributes and sub-objects while maintaining full object
> functionality.
> The Answer:
>   here is the answer I came up with, though it fits the task
> semanticly and I like how it works in concept, the application is
> rather time-critical thus this code does not fit the job...
>   does any one have an idea how to implement something with the same
> semantics but more efficiently (I'm intrested in a pure Python
> solution, not a C/C++ extention type)??      ...Thanks.

What about the code below?
I snipped it from Pyro and stripped it a bit.
Didn't do any comparison with your code, although yours
looks a lot more complex than this one...

Irmen de Jong


class DynamicProxy:
	def __init__(self, proxiedObject):
		# first set the list of 'local' attrs for __setattr__
		self.__dict__["_local_attrs"] = ("_local_attrs", "_name", "_proxiedObject" )
	def _r_ga(self, attr, value=0):
		if value: self._name.append("_r_ga")
		else: self._name.append("_r_ha")
		return self.__invokeOriginal__(attr)
	def findattr(self, attr):
		return self._r_ga(attr)
	def __setattr__(self, attr, value):
		if attr in self.__dict__["_local_attrs"]:
			result = self.findattr(attr)
			if result==2: # attribute
				return self.__invokeOriginal__(attr,value)
				raise AttributeError('not an attribute')
	def __getattr__(self, attr):
		# allows it to be safely pickeled
		if attr != "__getinitargs__":
			if result==1: # method
				return self.__invokeOriginal__
			elif result:
				return self._r_ga(attr, 1)
		raise AttributeError()
	def __invokeOriginal__(self, *vargs, **kargs):
		if methodName=="_r_ha":
				attr = getattr(self._proxiedObject ,vargs[0])
				if type(attr) in (UnboundMethodType, MethodType, BuiltinMethodType):
					return 1 # method
			return 2 # attribute
		elif methodName=="_r_ga":
			return getattr(self._proxiedObject, vargs[0])
		elif methodName=="_r_sa":
			return setattr(self._proxiedObject, vargs[0], vargs[1])
		method = getattr(self._proxiedObject, methodName )
		return apply(method, vargs, kargs)

# test

class Test:
	def __init__(self):
		print "init from test"
		self.attribute = 42
	def method(self, arg):
		print "method in test, arg=",arg
		return "result from test method!!!"
	def setAttribute(self, value):

object = Test()
proxy = DynamicProxy(object)

print "Calling method:"
print proxy.method("the arguments")
print "Printing attribute:"
print proxy.attribute
print "Setting attribute with method"
print "Printing attribute:"
print proxy.attribute
print "Setting attribute directly"
print "Printing attribute:"
print proxy.attribute
print "Printing original attribute:"
print object.attribute

More information about the Python-list mailing list