Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested classes for cleaner inheritance? [closed]

Tags:

python

oop

Say I have a class BigObject, which contains within it a number of SmallObjects - and this is the only place where SmallObject is used.

class SmallObject:
    pass

class BigObject:
    def __init__(self):
        self.objects = [SmallObject() for _ in range(10)]

This is all fine, until I want a second version of these two, which inherits some behaviour and overrides some; inheritance seems natural, except:

class NewSmallObject(SmallObject):
    pass

class NewBigObject(BigObject):
    def __init__(self):
        super().__init__()
        self.objects = [NewSmallObject for _ in range(10)]

We had to create a bunch of SmallObjects only to immediately override them with NewSmallObjects. Which is not great if e.g. SmallObjects are expensive to create. Also, if we change how the list of SmallObjects is created in BigObject, those changes don't get passed on to NewBigObject.

The solution I came up with was to use nested classes:

class BigObject:
    class SmallObject:
        pass
    def __init__(self):
        self.objects = [self.SmallObject() for _ in range(10)]

class NewBigObject(BigObject):
    class SmallObject(BigObject.SmallObject):
        pass

This deals with both the issues described above. My main concern is that when I looked on StackOverflow for questions about nested classes in Python people keep saying nested classes are unpythonic, and I'd like to understand why. It can also create quite deeply nested classes if SmallObject contains TinyObjects which contain MinisculeObjects etc, which may be the answer?

So my question is basically:

  • is this a "good" solution to this problem?

  • if not, what would a good alternative be?

like image 449
Christopher Avatar asked Jun 02 '26 15:06

Christopher


1 Answers

The solution is, as you've already found, to make SmallObject an attribute of the BigObject class.

There is nothing inherently wrong with using a nested class for this, but the readability of your code may suffer if the nested class is very long. Generally speaking, I would recommend to define SmallObject in the global scope though. After all, the Zen of Python says "Flat is better than nested". If you keep nesting TinyObjects and MinisculeObjects, your code will quickly become unreadable:

class BigObject:
    class SmallObject:
        class TinyObject:
            class MinisculeObject:
                ...  # MinisculeObject class body
            ...  # TinyObject class body
        ...  # SmallObject class body
    ...  # BigObject class body

Defining your classes in the global scope only requires minimal extra effort, and looks much cleaner:

class MinisculeObject:
    ...  # MinisculeObject class body

class TinyObject:
    miniscule_object_factory = MinisculeObject
    ...  # TinyObject class body

class SmallObject:
    tiny_object_factory = TinyObject
    ...  # SmallObject class body

class BigObject:
    small_object_factory = SmallObject
    ...  # BigObject class body
like image 192
Aran-Fey Avatar answered Jun 05 '26 03:06

Aran-Fey



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!