0

In many of the problems I work on, I find that I'll have a custom class, then a container class that stores those objects and methods that acts on all the objects in the class.

For example, consider a curve class, and a container.

class Curve:
    def __init__(self, args):
        self.label

    def getLength(self):
        # code that gets length
...

curves = [curve1, curve2, ..., ]

class CurvesContainer:
    def __init__(self, curves):
        self.curves = curves
        ...

    def setLabels(self, labels):
        for curve, label in zip(self.curves, labels):
            curve.label = label 

    def getLengths(self):
        lengths = []
        for curve in self.curves:
            lengths.append(curve.getLength())
        return lengths

curve1 = container.curves[1]

However, if we use this setup, we end up with calling container.curves/self.curves a lot - kind of ugly!

It seems a way of refactoring this would be to inherit from list as follows:

class CurvesContainer(list):
    def __init__(self, curves):
        super().__init__(curves)

    def setLabels(self, labels):
        for curve, label in zip(self, labels):
            curve.label = label 

    def getLengths(self):
        lengths = []
        for curve in self:
            lengths.append(curve.getLength())
        return lengths

curve1 = container[1]

However, I don't see this done much in practice - I'm wondering if this is bad form for some reason?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
cslotboom
  • 31
  • 3
  • It doesn't seem like this class has a good reason to exist. It doesn't represent a meaningful abstraction or offer useful functionality. You could just use a normal list. – user2357112 Aug 28 '21 at 08:37
  • This yet one more iteration of the [prefer composition over inheritance](https://stackoverflow.com/q/49002/2311167) question – Adrian W Aug 28 '21 at 08:52

2 Answers2

4

There is the general OOP principle of composition over inheritance:

Composition over inheritance in object-oriented programming is the principle that classes should achieve polymorphic behavior and code reuse by their composition (by containing instances of other classes that implement the desired functionality) rather than inheritance from a base or parent class. This is an often-stated principle of OOP, such as in the influential book Design Patterns (1994).

One problem is that all the methods of list that return a new list still return a list. If you slice your new CurvesContainer, you'll get a list. If you concatenate two CurvesContainers, you'll get a list. And so on. If that's not what you want, you'll need to re-implement all these methods yourself.

Jasmijn
  • 9,370
  • 2
  • 29
  • 43
0

It's not a bad practice and actually a good use of class inheritance.

The other option would be to implement a __iter__ method, but it would only enable the iterating aspect of lists.

Your example is perfectly valid and good practice

Lord Baryhobal
  • 132
  • 1
  • 7