Skip to content Skip to sidebar Skip to footer

List Of All Python Dunder Methods - Which Ones Do You Need To Implement To Correctly Proxy An Object?

I'm trying to create an object proxy. Attribute/property lookup can be done by simply implementing the __getattribute__, __setattr__ and __delattr__ methods. However, other functio

Solution 1:

To proxy an object, you only need to implement the dunder methods that the object has, so in the simplest world, you wouldn't need to do anything special to proxy them that you're not already doing to proxy the object's other attributes.

However, the wrinkle is that dunder methods are looked up on the class, not on the object, so while for example Foo().bar will look up bar on the instance before falling back to the class if the instance has no bar attribute, Foo() + 5 will look up __add__ on the class Foo, completely ignoring the instance. That is, if the instance does have an instance attribute named __add__, then Foo() + 5 still won't use that instance attribute.

So to proxy those dunder methods, they need to be proxied at the class level, not the instance level.

from functools import wraps

defproxy_function(name, f):
    @wraps(f)defproxied_f(*args, **kwargs):
        print('Proxying function:', name)
        return f(*args, **kwargs)
    return proxied_f

defproxy_object(obj):
    classProxy:
        def__getattr__(self, name):
            print('Proxying getattr:', name)
            returngetattr(obj, name)
        def__hasattr__(self, name):
            print('Proxying hasattr:', name)
            returnhasattr(obj, name)
        def__setattr__(self, name, value):
            print('Proxying setattr:', name, '=', repr(value))
            setattr(obj, name, value)
        def__delattr__(self, name):
            print('Proxying delattr:', name)
            delattr(obj, name)
    
    for name, f in obj.__class__.__dict__.items():
        # don't try to overwrite __class__, __getattr__, etc.ifcallable(f) and name notin Proxy.__dict__:
            f = proxy_function(name, f)
            setattr(Proxy, name, f)
    
    return Proxy()

Usage:

>>> classFoo:
... def__add__(self, other):
... return'Adding with ' + repr(other)
... >>> foo = Foo()
>>> proxy_foo = proxy_object(foo)
>>> foo + 5'Adding with 5'>>> proxy_foo + 5
Proxying function: __add__
'Adding with 5'

Post a Comment for "List Of All Python Dunder Methods - Which Ones Do You Need To Implement To Correctly Proxy An Object?"