Tech Blog by Ruddra

Create Proxy Object in Python

Lets say you have been using a class named ClassA, objects created from that class has been used in many places. Now you have a requirement that you need to make a simillar class ClassB, which has almost simillar functionality. Objects of ClassA and ClassB will have simillar method signatures, and could be swapable. Or in many places, instead of ClassA you need to use ClassB. So how can you do that? Answer is, make a proxy class.

Purpose of Proxy Object

The Proxy class instance will be acting as instance of either class ClassA or ClassB depending on certain conditions. You can put that logic inside Proxy Class.

Implementation

from path.to.a import ClassA
from path.to.b import ClassB

class ProxyClass(object):
    def do_some_condition_checks(self, *args, **kwargs):
        # do conditon checks
        return True  # Or False

    def __init__(self, *args, **kwargs):
        condition = self.do_some_condition_checks(*args, **kwargs)
        object.__setattr__(
            self,
            "_obj",
            ClassA(*args, **kwargs) if condition else ClassB(*args, **kwargs)
        )

    #
    # proxying (special cases)
    #
    def __getattribute__(self, name):
        return getattr(object.__getattribute__(self, "_obj"), name)

    def __delattr__(self, name):
        delattr(object.__getattribute__(self, "_obj"), name)

    def __setattr__(self, name, value):
        setattr(object.__getattribute__(self, "_obj"), name, value)

    def __nonzero__(self):
        return bool(object.__getattribute__(self, "_obj"))

    def __str__(self):
        return str(object.__getattribute__(self, "_obj"))

    def __repr__(self):
        return repr(object.__getattribute__(self, "_obj"))

    def __hash__(self):
        return hash(object.__getattribute__(self, "_obj"))

Explanation

Here we will be setting an attribute _obj inside Proxy class which will be either an instance of ClassA or ClassB. Then we have provided overrides for built-in functions inside an object, which will get attributes from _obj instead of the Proxy object itself.

Usage

from path.to.proxy import ProxyClass

instance = ProxyClass(foo_bar, foo=bar)

How It helps

Lets say you have usage of ClassA in many places of the code, where you might need to use ClassB when certain conditions meet. There you can simply use ProxyClass’s object so that you don’t need to define if/else conditons everywhere. It will make code cleaner, also if you need to change some conditions, you can change it in ProxyClass, then the logic will be reflected everywhere. You can even make less change, with naming the proxy class as ClassA, then you don’t have to change import references everywhere.

Thanks

I got help from this link.