Reputation: 524
I want some Python class having similar methods as list
(assuming it's called mylist
) except that mylist
accepts elements of a specific type (instances of another customed class to store some data in my case).
I read some posts on SO and knew that I need to override some methods as append
, extend
, insert
. But I'm not sure about everything I need to override to guarantee that in all operations (e.g. append, add, extend, insert, slice...) to instances of mylist
there will be no problem.
And if there is one more convenient way without needs to override so many methods?
Upvotes: 0
Views: 528
Reputation: 310217
Sometimes, things are easier without inheriting from builtin objects...:
from collections import MutableSequence, Iterable
class MyList(MutableSequence):
def __init__(self, type, iterable=()):
self._data = []
self._type = type
self.extend(iterable)
def insert(self, index, item):
if not isinstance(item, self._type):
raise TypeError
self._data.insert(index, item)
def __len__(self):
return len(self._data)
def __getitem__(self, *args):
return self._data.__getitem__(*args)
def __delitem__(self, *args):
self._data.__delitem__(*args)
def __setitem__(self, key, value):
if isinstance(value, collections.Iterable) and isinstance(key, slice):
values = []
for val in value:
if not isinstance(value, self._type):
raise TypeError
else:
if not isinstance(value, self._type):
raise TypeError
self._data[k] = value
Note, I haven't gone into any discussion about whether this is a good idea. Some people will tell you not to do this because python is built on "duck-typing". Others say that isinstance
is perfectly fine to use -- provided that you do so responsibly. One proponent of this view (Alex Martelli) is generally regarded as a python expert. He recommends isinstance
checking against abstract base classes and calls this practice "goose-typing". This practice seems to have gained some traction as the standard library is slowly adding support that would allow more robust run-time checking of these things -- Consider PEP-0484 (type hinting).
I suppose, my point is that if you use this class, don't do:
lst1 = MyList(list)
lst2 = MyList(int)
Do something like:
lst1 = MyList(collections.MutableSequence)
lst2 = MyList(numbers.Integral)
Upvotes: 4