Home > Blockchain >  Choosing between base class or extended class - Python
Choosing between base class or extended class - Python

Time:10-23

I have a Python library which will be used by other people:

class BaseClassA:
   

class BaseClassB:
    def func0(self):
        this.class_a_obj = BaseClassA()

BaseClassB creates a BaseClassA object and stores a pointer. This is an issue because I want to allow the user to extend my library classes:

class ExtendClassA(BaseClassA):

And my library should choose the extended class (ExtendClassA) instead of the base class (BaseClassA) in the func0 method.

Above is a very simple example my problem statement. In reality I have 10ish classes where extending/creation happens. I want to avoid the user having to rewrite func0 in an extended BaseClassB to support the new ExtendClassA class they created.

I'm reaching out to the stack overflow community to see what solutions other people have implemented for issues like this. My initial thought is to have a global dict which 'registers' class types/constructors and classes would get the class constructors from the global dict. When a user wants to extend a class they would replace the class in the dict with the new class.

Library code:

global lib_class_dict
lib_class_dict['ClassA'] = BaseClassA()
lib_class_dict['ClassB'] = BaseClassB()

class BaseClassA:
   

class BaseClassB:
    def func0(self):
        this.class_a_obj = lib_class_dict['ClassB']

User code:

lib_class_dict['ClassA'] = ExtendClassA():


class ExtendClassA:

EDIT: Adding more details regarding the complexities I'm dealing with.

I have scenarios where method calls are buried deep within the library, which makes it hard to pass a class from the user entry point -> function:

(user would call BaseClassB.func0() in below example)

class BaseClassA:
   

class BaseClassB:
    def func0(self):
        this.class_c_obj = BaseClassC()

class BaseClassC:
    def __init__(self):
        this.class_d_obj = BaseClassD()

class BaseClassD:
    def __init__(self):
        this.class_a_obj = BaseClassA()

Multiple classes can create one type of object:

class BaseClassA:
   

class BaseClassB:
    def func0(self):
        this.class_a_obj = BaseClassA()

class BaseClassC:
    def __init__(self):
        this.class_a_obj = BaseClassA()

class BaseClassD:
    def __init__(self):
        this.class_a_obj = BaseClassA()

For these reasons I'm hoping to have a global or central location all classes can grab the correct class.

CodePudding user response:

Allow them to specify the class to use as an optional parameter to func0

def BaseClassB:
    def func0(self, objclass=BaseClassA):
        self.class_a_obj = objclass()

obj1 = BlassClassB()
obj1.func0()
obj2 = BassClassB()
obj2.func0(objclass = ExtendClassA)

CodePudding user response:

Here is how I would do it.

A super class HasRef has as class attributes, the class of the objects that are referenced by its instances (ref_cls) and the name of the attribute (ref_name) that references these.

Then the sub classes can overload ref_cls and ref_name with the appropriate class and attribute name.

With your last example, that would give the following:

class BaseClassA:
    pass

class HasRef:
    ref_cls = BaseClassA
    ref_name = 'class_a_obj'
    
    def __init__(self):
        setattr(self, self.ref_name, self.ref_cls())

class BaseClassD(HasRef):
    pass

class BaseClassC(HasRef):
    ref_cls = BaseClassD
    ref_name = 'class_d_obj'

class BaseClassB(HasRef):
    ref_cls = BaseClassC
    ref_name = 'class_c_obj'

d = BaseClassD()
b = BaseClassB()
c = BaseClassC()

print(type(d.class_a_obj))  # <class '__main__.BaseClassA'
print(type(c.class_d_obj))  # <class '__main__.BaseClassD'
print(type(b.class_c_obj))  # <class '__main__.BaseClassC'
  • Related