Same name functions in same class - is there an elegant way to determine which to call? Same name functions in same class - is there an elegant way to determine which to call? python python

Same name functions in same class - is there an elegant way to determine which to call?


Inheritance is probably the best way to do this, but since you asked specifically about decorators, I wanted to show you could do this using decorators.

You'll need to use a dictionary to store your functions by version, and then look up which version to use at runtime. Here's an example.

version_store = {}def version(v):    def dec(f):        name = f.__qualname__        version_store[(name, v)] = f        def method(self, *args, **kwargs):            f = version_store[(name, self.version)]            return f(self, *args, **kwargs)        return method    return decclass Product(object):    def __init__(self, version):        self.version = version    @version("1.0")    def function(self):        print("1.0")    @version("2.0")    def function(self):        print("2.0")Product("1.0").function()Product("2.0").function()


Could you put your Product class into two modules, v1 and v2, then import them conditionally?

For example:

Productv1.py

class Product(object):    def function():        print('for version 1.0')

Productv2.py

class Product(object):    def function():        print('for version 2.0')

Then in your main file:

main.py

if client.version == '1.0':    from Productv1 import Productelif client.version == '2.0':    from Productv2 import Productelse:    print(f'function not support {self.version}')p = Productp.function()


As another option, you could go for some factory to create your class.

Create your versioned functions (note the self parameter). This can be done in a different module. Also, add some collection to fetch the function based on the version number.

def func_10(self):    print('for version 1.0')def func_20(self):    print('for version 2.0')funcs = {"1.0": func_10,         "2.0": func_20}

Add a base class that contains the static parts of your implementation and a utility class to create your instances in:

class Product:    def __init__(self, version):        self.version = versionclass ProductFactory(type):    @classmethod    def get_product_class(mcs, version):        # this will return an instance right away, due to the (version) in the end        return type.__new__(mcs, "Product_{}".format(version.replace(".","")), (Product,), {"function": funcs.get(version)})(version)        # if you want to return a class object to instantiate in your code omit the (version) in the end

Using this:

p1 = ProductFactory.get_product_class("1.0")p2 = ProductFactory.get_product_class("2.0")print(p1.__class__.__name__) # Product_10p1.function() # for version 1.0print(p1.function) # <bound method func_10 of <__main__.Product_10 object at 0x0000000002A157F0>>print(p2.__class__.__name__) # Product_20p2.function() # for version 2.0 print(p2.function) # <bound method func_20 of <__main__.Product_20 object at 0x0000000002A15860>>