The goal of the code below is to have an abstract base class that defines simple methods and attributes for the subclasses. This is part of an application that provides the code base for others to develop their own subclasses such that all methods and attributes are well implemented in a way for the main application to use them. The application shall never create more than one object of each subclass, since they are supposed to implement everything correctly to be called upon. Ideally, instantiating objects of the subclasses would not even be necessary, but is needed as it is in order to check if the abstract methods are implemented.
However, Python seems to be different and awkward when it comes to classes in comparison with other programming languages (initialization, attributes, properties), and I am not very sure if the solution below is the most appropriate. It seems too much complicated to achieve the aforementioned purpose. In addition, another function (not in the code below) must be made to properly check (make sure that they are of a certain type) the attributes of the subclasses.
from abc import ABC, abstractmethod class abstract_attribute(object): """taken from http://stackoverflow.com/questions/32536176/how-to-define-lazy-variable-in-python-which-will-raise-notimplementederror-for-a/32536493#32536493""" def __get__(self, obj, type): # Now we will iterate over the names on the class, # and all its superclasses, and try to find the attribute # name for this descriptor # traverse the parents in the method resolution order for cls in type.__mro__: # for each cls thus, see what attributes they set for name, value in cls.__dict__.items(): # we found ourselves here if value is self: # if the property gets accessed as Child.variable, # obj will be done. For this case # If accessed as a_child.variable, the class Child is # in the type, and a_child in the obj. this_obj = obj if obj else type raise NotImplementedError( "%r does not have the attribute %r " "(abstract from class %r)" % (this_obj, name, cls.__name__)) # we did not find a match, should be rare, but prepare for it raise NotImplementedError( "%s does not set the abstract attribute <unknown>", type.__name__) class Base(ABC): # attr1 and attr2 must be properly (be of a certain type) implemented by subclasses # abstract_attribute() checks if the attribute is present in the subclass attr1 = abstract_attribute() attr2 = abstract_attribute() @abstractmethod def method(): pass # a class property that does not change from instance to instance @property def prop(self): return self.prop @prop.setter @classmethod def prop(self, prop): self.prop = prop class Sub(Base): # attr1 and attr2 must be implemented otherwise and exception is thrown upon accessing them attr1 = something attr2 = somethingElse # method must be implemented otherwise an exception is thrown upon instantiation def method(): print("must be implemented by subclasses")