2

in my example I have a base class Processing, which handles all pre- and post processing. This class is meant to be inherited from, when an algorithm is implemented. After the implementation I would like to call all inherited instances and compare the results. What I would like to know: is there a way to automatically call all inherited instances without having to do so manually. Or even better: is there a way to detect all inherited classes, so that I do not need to do any "book-keeping" anywhere? To better explain my problem I have written a little example:

class BaseProcessing:
  def __init__(self, _data):
    self.data = _data

  def __call__(self):
    self.do_pre_processing()
    self.do_algorithm()
    self.do_post_processing()

  def do_pre_processing(self):
    """generic preprocessing steps"""
    print("Starting preprocessing")

  def do_algorithm(self):
    raise RuntimeError('Please inherit from this class and implement algorithm.')

  def do_post_processing(self):
    """generic post processing steps"""
    print("Starting post processing")

class SimpleAlgorithm(BaseProcessing):
  def do_algorithm(self):
    print("Simple calculations")


class SplineAlgorithm(BaseProcessing):
  def do_algorithm(self):
    print("Using splines for calculation")
...


if __name__ == "__main__":
    data = getData()

    # is there a way to automate the following code,
    # which automatically can detect all the inherited instances?
    simple = SimpleAlgorithm(data)
    simple()
    spline = SplineAlgorithm(data)
    spline()
    ...

kayos
  • 53
  • 6
  • Classes, in general, don't keep track of their instances. Typically, it is *your job* as a programmer to organize your data structures in the way that makes it convenient to accomplish what you need. Probably, using some other, container class created for this purpose – juanpa.arrivillaga Oct 19 '21 at 16:43
  • 1
    `for cls in BaseProcessing.__subclasses__(): cls(data)()` – ekhumoro Oct 19 '21 at 16:46

2 Answers2

4

You can use BaseProcessing.__subclasses__() to get a list of classes that have used BaseProcessing as a base class. I suppose, you could do something like:

for subclass in BaseProcessing.__subclasses__():
    instance = subclass(data)
    instance()

In general, though, I would be inclined to use something more explicit. Maybe something like:

class Pipeline:
    def __init__(self, data):
        self.data = data
        self.processes = []
        self.result = []
    def register(self, cls):
        self.processes.append(cls)
        return cls
    def run(self):
        for cls in self.processes:
            instance = cls(self.data)
            result.append(instance())
    
pipeline = Pipeline(data)


@pipeline.register
class SimpleAlgorithm(BaseProcessing):
  def do_algorithm(self):
    print("Simple calculations")

@pipeline.register
class SplineAlgorithm(BaseProcessing):
  def do_algorithm(self):
    print("Using splines for calculation")

pipeline.run()
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
0

It's a little unclear what you're trying to do, but it sounds like you want a centralized registry of all implementations of the parent class. Once you have that, you can write functions to iterate through it for whatever purpose.

This earlier Q&A looks at some ways of doing that. A class decorator may be a good way of performing the registration. Of course (?) it would be ideal to have the registration happen automatically any time you subclass; a meta-class may let you do that, you'll need to experiment (or find someone who knows them better than I).

ShapeOfMatter
  • 991
  • 6
  • 25