I am trying to define a default style list object:
class ilist(list):
def __init__(self,r=list(),dft=None):
list.__init__(self,r)
self.dft=dft
def __getitem__(self,n):
if len(self)<=n:
for i in range(n-len(self)+1):
self.append(self.dft)
for i,v in enumerate(self):
if i+1==len(self):
return v
x=ilist()
print x[4]
print x
It works.
>>>
None
[None, None, None, None, None]
But I think it's terrible to query my ilist. I've tried the following method:
def __getitem__(self,n):
from operator import getitem
if len(self)<=n:
for i in range(n-len(self)+1):
self.append(self.dft)
return getitem(self,n)
but the fact shows it totally equals self[n] and causes RuntimeError: maximum recursion depth exceeded
I also tried to borrow the parent class list
method .But the form isx.__getitem__(y)
. I don't know how to adapt it to ilist.
So finally my terrible solution comes out. Raw and brute force..Is there any effecient or simple solution? Thanks in advance.
Use super()
to access the original __getitem__
:
def __getitem__(self,n):
while len(self) <= n:
self.append(self.dft)
return super(ilist, self).__getitem__(n)
Demo:
>>> class ilist(list):
... def __init__(self,r=list(),dft=None):
... list.__init__(self,r)
... self.dft=dft
... def __getitem__(self, n):
... while len(self) <= n:
... self.append(self.dft)
... return super(ilist, self).__getitem__(n)
...
>>> il = ilist()
>>> il[3]
>>> il
[None, None, None, None]
>>> il[2] = 5
>>> il
[None, None, 5, None]
>>> il[2]
5
You probably want to support slicing as well:
def __getitem__(self, n):
maxindex = n
if isinstance(maxindex, slice):
maxindex = maxindex.indices(len(self))[1]
while len(self) <= maxindex:
self.append(self.dft)
return super(ilist, self).__getitem__(n)
and if you wanted to support assignment to arbitrary indices as well, add a __setitem__
method:
def __setitem__(self, n, val):
maxindex = n
if isinstance(maxindex, slice):
maxindex = maxindex.indices(len(self))[1]
while len(self) <= maxindex:
self.append(self.dft)
return super(ilist, self).__setitem__(n, val)
but then you could move the default-value creation out to a helper method:
class ilist(list):
def __init__(self, r=None, dft=None):
if r is None:
r = []
list.__init__(self, r)
self.dft=dft
def _ensure_length(n):
maxindex = n
if isinstance(maxindex, slice):
maxindex = maxindex.indices(len(self))[1]
while len(self) <= maxindex:
self.append(self.dft)
def __getitem__(self, n):
self._ensure_length(n)
return super(ilist, self).__getitem__(n)
def __setitem__(self, n, val):
self._ensure_length(n)
return super(ilist, self).__getitem__(n)