What to consider before subclassing list?
I was recently going over a coding problem I was having and some开发者_运维问答one looking at the code said that subclassing list was bad (my problem was unrelated to that class). He said that you shouldn't do it and that it came with a bunch of bad side effects. Is this true?
I'm asking if list is generally bad to subclass and if so, what are the reasons. Alternately, what should I consider before subclassing list in Python?
The abstract base classes provided in the collections
module, particularly MutableSequence
, can be useful when implementing list-like classes. These are available in Python 2.6 and later.
With ABCs you can implement the "core" functionality of your class and it will provide the methods which logically depend on what you've defined.
For example, implementing __getitem__
in a collections.Sequence
-derived class will be enough to provide your class with __contains__
, __iter__
, and other methods.
You may still want to use a contained list object to do the heavy lifting.
There are no benefits to subclassing list
. None of the methods will use any methods you override, so you can have unexpected bugs. Further, it's very often confusing doing things like self.append
instead of self.foos.append
or especially self[4]
rather than self.foos[4]
to access your data. You can make something that works exactly like a list or (better) howevermuch like a list you really want while just subclassing object
.
I think the first question I'd ask myself is, "Is my new object really a list?". Does it walk like a list, talk like a list? Or is is something else?
If it is a list, then all the standard list methods should all make sense.
If the standard list methods don't make sense, then your object should contain a list, not be a list.
In old python (2.2?) sub-classing list was a bad idea for various technical reasons, but in a modern python it is fine.
Nick is correct. Also, while I can't speak to Python, in other OO languages (Java, Smalltalk) subclassing a list is a bad idea. Inheritance in general should be avoided and delegation-composition used instead.
Rather, you make a container class and delegate calls to the list. The container class has a reference to the list and you can even expose the calls and returns of the list in your own methods. This adds flexibility and allows you to change the implementation (a different list type or data structure) later w/o breaking any code. If you want your list to do different listy-type things then your container can do this and use the plain list as a simple data structure. Imagine if you had 47 different uses of lists. Do you really want to maintain 47 different subclasses? Instead you could do this via the container and interfaces. One class to maintain and allow people to call your new and improved methods via the interface(s) with the implementation remaining hidden.
精彩评论