-1

I want to define a simple child class that inherits all of the parent's methods and introduces some new ones. The caveat: I don't want to have to specify what the parent class is, as I want this child class to be compatible with a broad set of classes. Is there a way to do this?

If not, then what is the best way to create a new class that inherits all the methods from any other class and introduces new methods?

martineau
  • 119,623
  • 25
  • 170
  • 301
DaltonicD
  • 75
  • 2
  • 7

1 Answers1

2

What you're looking for is typically referred to as a mixin. Take these classes for example.

class FooBase:
    def data(self):
        return "foo"


class BarBase:
    def data(self):
        return "bar"

Both define data method but are themselves different classes. If we wanted to provide some mixin class that can print the value from data we could do so like this:

from abc import ABC, abstractmethod


class PrintDataMixin(ABC):
    @abstractmethod
    def data(self):
        pass

    def print_data(self):
        print(self.data())

Here we're saying that the PrintDataMixin mixin can be applied to any class that has a data method implemented. FooBase and BarBase could have completely different sets of methods defined, but as long as they have the data method defined they will satisfy usage with PrintDataMixin.

Example usage for extending FooBase and BarBase with this mixin:

class FooImpl(FooBase, PrintDataMixin):
    pass


class BarImpl(BarBase, PrintDataMixin):
    pass


FooImpl().print_data()
BarImpl().print_data()
foo
bar

Update:

You could try to do this more generically any point you want, but in general I find dynamic classes like that hard to work with especially when you need to debug the application. It also makes it harder for static analyzers like mypy to determine if you are using classes correctly.

It's much easier to determine what's going on when classes are well defined in the source.

To dynamically create a class with a mixin applied you could do something like this:

def class_of(*cls):
    class NewClass(*cls):
        pass
    return NewClass


class_of(BaseClass, MixinClass)(*args, **kwargs).print_data()
flakes
  • 21,558
  • 8
  • 41
  • 88
  • Right, but even mixin still forces me to list every parent class, correct? Is there any way to avoid this? In other words, could I make a class Child(generic_parent) where only when I instantiate an object do I decide the specific parent class? – DaltonicD Dec 04 '21 at 19:52
  • 1
    @DaltonicD I advise against it, but I updated how you could. – flakes Dec 04 '21 at 22:34
  • Thanks! You say you advise against it. Would it be better, then, to define a function that adds the desired methods to an instantiated object, instead of building a new class? – DaltonicD Dec 04 '21 at 23:11
  • @DaltonicD It seems like unnecessary complexity, especially when creating a new class is easy (and from this example already very succinct). This is a personal opinion, but I avoid inheritance where I can, if I can use more basic structures. Why does the method need to be on the class at all? If the method doesn't need to be class specific, there's not much point having it on the class in the first place. You can always create a stateless function that accepts a class instance with a specific interface. Making the class construction dynamic only adds another layer to the complexity onion. – flakes Dec 04 '21 at 23:28