I am trying to better understand composition vs inheritance in python so I have crafted a hopefully simple example.
Suppose I want to implement a class TitledList
that is intended to behave just like a standard list, but with an additional attribute title
intended to hold a string containing the name of the list. The __repr__
and __str__
methods would likely have to be reimplemented to incorporate the title, but otherwise I'd like to retain all the native functionality of list
. Initializers would accept an optional keyword-only argument title
.
I can see two approaches to creating this class. I could go the composition route, and define a class with two attributes, .contents
(a regular list) and .title
. That would presumably look something along the lines of
class TitledList:
def __init__(self, contents=[], *, title=None):
self.contents = list(contents)
self.title = title
But I'm not sure how I would go about cribbing all the methods of list
so I don't have to constantly be referring to my_titled_list.contents
all over the place or reimplement all the list methods I use.
The other alternative is to do the thing that everyone on the whole Internet says not to do, and inherit from the list
class. I think in that case I would do the initializer like this?
class TitledList(list):
def __init__(self, iterable=[], *, title=None):
super().__init__(iterable)
self.title = title
This seems a lot more straightforward to me. But surely everyone on the whole Internet says not to extend list
for a reason.
What are the pros and cons here? Is there a simple way to make the composition solution work the way I intuitively want? Are there lots of drawbacks to the inheritance solution that I don't understand? Is there some third option I should be considering (UserList
?)