🐍 Python - Inheritance
Prefer composition over inheritance.
Understand the difference between interface inheritance and implementation inheritance. Interface inheritance creates "is-a" relationships, abstract base classes. Implementation inheritance allows code reuse, concrete classes and mixins.
Use mixins for code reuse. Mixin bundles methods for reuse, mixin does not define an "is-a" relationship. But even if mixins don't define type, they should have well defined purpose.
It's recommended to suffix your mixin names with ...Mixin
.
Don't subclass from more than one concrete class. Only one subclass should be something other that abstract base class or mixin. Inheriting multiple concrete classes makes applications over complex.
class MyConcreteClass(Alpha, BaseBeta, GammaMixin):
pass
Create aggregate classes. Aggregate classes don't have any body but group classes together for easier use.
class Widget(BaseWidget, PlaceMixin, GridMixin):
pass
Avoid subclassing built-in types like list
or dict
Subclassing built-in types is tricky because extended built-in classes don't first search for methods on itself, thus ignoring user-defined overrides. If you need to subclass a built-in type, use e.g. collections.UserDict
or collections.UserList
.
class DoubleDict(dict):
def __setitem__(self, key, value) -> None:
super().__setitem__(key, [value] * 2)
dd = DoubleDict(one=1)
assert dd == {'one': 1} # NOT duplicated
dd['two'] = 2
assert dd['two'] == [2, 2] # ok, duplicated
dd.update(three=3)
assert dd['three'] == 3 # NOT duplicated
Source
- Fluent Python, Luciano Ramalho