-4

I have the following class inheritance in Python:

A
|
B--D
|  |
C  E

What bothers me is that I have a lot of duplicate class methods in C and E. This can be avoided if I make E a child of C instead of D, but then I'd have to duplicate D's methods in E.

Is there a way for E to subclass both D and C so that E has functions from both C and D?

Sibbs Gambling
  • 19,274
  • 42
  • 103
  • 174
  • 5
    `class E(C,D):...`? – wwii Dec 30 '20 at 16:11
  • 2
    Yes, Python allows multiple inheritance. – chepner Dec 30 '20 at 16:12
  • 2
    or move shared code into another class and derive both from that – Sam Mason Dec 30 '20 at 16:12
  • @wwii oh would that work? In that case, what would `super().__init__()` be? C's or D's? – Sibbs Gambling Dec 30 '20 at 16:12
  • 2
    @SibbsGambling search for MRO, i.e method resolution order – Sam Mason Dec 30 '20 at 16:13
  • 2
    If you are using `super`, *every* class should use `super`. The order in which each individual class's `__init__` method is called depends on the final method resolution order. – chepner Dec 30 '20 at 16:13
  • 1
    [https://docs.python.org/3/tutorial/classes.html#inheritance](https://docs.python.org/3/tutorial/classes.html#inheritance) ... [https://www.python.org/download/releases/2.3/mro/](https://www.python.org/download/releases/2.3/mro/) – wwii Dec 30 '20 at 16:15
  • 1
    Using wii's suggestion, the method resolution order would be E, C, B, D, A, object. Note that this means that `D.__init__` would be called from `B.__init__`, even though `B` does not inherit from D. `super` is a somewhat misnamed class. – chepner Dec 30 '20 at 16:18
  • 1
    [The Art of Subclassing](https://pyvideo.org/europython-2011/the-art-of-subclassing-0.html) - EuroPython Pyvideo - I think there are also videos of this talk at other venues. – wwii Dec 30 '20 at 16:20
  • 1
    Or maybe I meant [Python’s super() considered super!](https://rhettinger.wordpress.com/2011/05/26/super-considered-super/). Related:[Python multi-inheritance, __init__](https://stackoverflow.com/questions/8688114/python-multi-inheritance-init) ... [Calling parent class __init__ with multiple inheritance, what's the right way?](https://stackoverflow.com/questions/9575409/calling-parent-class-init-with-multiple-inheritance-whats-the-right-way). – wwii Dec 30 '20 at 16:28
  • 1
    Does [How does Python's super() work with multiple inheritance?](https://stackoverflow.com/questions/3277367/how-does-pythons-super-work-with-multiple-inheritance) answer your question? – wwii Dec 30 '20 at 16:33

5 Answers5

2

You can make multiple inheritance. You have a lot of posibilities when you implement this, so it depends on your needs.

For example:

class E(C, D):
   pass

Check this out: https://www.programiz.com/python-programming/multiple-inheritance

Santi Rodriguez
  • 164
  • 1
  • 9
1

You can certainly. Check out this resource https://pythonprogramminglanguage.com/multiple-inheritance/#:~:text=In%20Python%20a%20class%20can,concept%20from%20object%20orientated%20programming.

class A:
    pass

class B(A):
    pass

class C(B):
    pass

class D(B):
    pass

class E(C, D):
    pass
mandulaj
  • 733
  • 3
  • 10
1

You can subclass multiple classes as follows

class C:
   pass
class D:
   pass
class E(C, D):
   pass

You may even create a mixin (which is just a class that's not meant to be used standalone) and put the common features there, and add that mixin to your classes that need those features.

What is a mixin, and why are they useful?

Victor
  • 2,864
  • 1
  • 12
  • 20
1

One of solutions is to extract methods duplicated in C and E to a new class F and let C and E inherit from F. In most cases it is called Mixin. Look at this answer for more explanation: https://stackoverflow.com/a/547714/3421655.

Lukasz Puchala
  • 466
  • 1
  • 6
  • 11
1

You can inherit from two classes at once:

class a(b, c):
    pass

So, if in b, thing1 = 123 and in c, thing2 = 64, a would have both of those variables.

>>> a.thing1
123
>>> a.thing2
64

But if class a is like this:

class a(b, c):
    thing3 = 42

Using dir(a), in the end of the huge list would appear:

'thing1', 'thing2', 'thing3'

Therefore, you can do this:

>>> a.thing3
42

But not this (I assume):

>>> c.thing3
BlueStaggo
  • 171
  • 1
  • 12