I found an example of multiple inheritance but don't understand the way it behaves.
class Printable:
"""A mixin class for creating a __str__ method that prints
a sequence object. Assumes that the type difines __getitem__."""
def lef_bracket(self):
return type(self).__name__ + "["
def right_bracket(self):
return "]"
def __str__(self):
result = self.lef_bracket()
for i in range(len(self)-1):
result += str(self[i]) + ", "
if len(self) > 0:
result += str(self[-1])
return result + self.right_bracket()
This script is stored in printable.py so the class Printable
is used in this way:
>>> from printable import *
>>> class MySeq(list, Printable):
... pass
...
>>> my_seq = MySeq([1,2,3])
>>> print(my_seq)
MySeq[1, 2, 3]
My question is that why the __str__
method is inherited from the Printable
class instead of the list
class, while the Method Resolution Order of MySeq
is:
>>> MySeq.__mro__
(<class '__main__.MySeq'>, <class 'list'>, <class 'printable.Printable'>, <class 'object'>)
In the docstring of Printable
I notice the word "mixin". Why in this case we call it a mixin class?
list
doesn't define a __str__
method:
>>> '__str__' in list.__dict__
False
Because it doesn't define such a method, the next class in the MRO gets to supply it. For a plain list
object, that'd be object.__str__
:
>>> list.__mro__
(<class 'list'>, <class 'object'>)
>>> list.__str__ is object.__dict__['__str__']
True
but because Printable
is mixed in, it is listed before object
:
>>> MySeq.__mro__
(<class '__main__.MySeq'>, <class 'list'>, <class '__main__.Printable'>, <class 'object'>)
>>> MySeq.__str__ is Printable.__dict__['__str__']
True
A mix-in class is a class designed to be added into a class hierarchy to work together with other base classes. Printable
is a mix-in because it requires that something else implements __getitem__
.