While implementing a custom list (via UserList
) I noticed that all slicing operations return a type of list
not of the derived class type. This creates an issue that, after slicing, none of the added functionality is available in the object. Here is a quick test program to demonstrate the issue, just note the the actual code is more complicated.
#!/usr/bin/python3
from collections import UserList
class myList(UserList):
def __init__(self, data=None):
super().__init__(data)
def setFunc(self, data):
self.data.extend(data)
def getFunc(self):
return self.data
l1 = myList()
l1.setFunc([1,2,3,4])
print(type(l1))
l2 = l1[:3]
print(type(l2))
print(l2.getFunc())
<class '__main__.myList'>
<class 'list'>
Traceback (most recent call last):
File "./test.py", line 17, in <module>
print(l2.getFunc())
AttributeError: 'list' object has no attribute 'getFunc'
I can overcome this issue by "casting" the list
with l2 = myList(l1[:3])
but it seems like the right solution would be to implement this functionality directly in myList
.
I'm not certain the correct/most-elegant way to do this. I suspect putting a cast in __getitem__
would work. Is that the best way or is there a more direct change to the slicing that would be preferred? Also, what other methods should I override in order to assure all operations return a myList
not a list
?
I'm not sure why this isn't the default behavior in UserList
but implementing the following in the derived class seems to fix the issue.
def __getitem__(self, i):
new_data = self.data[i]
if type(new_data) == list:
return self.__class__(new_data)
else:
return new_data
The parameter i
for __getitem__
apparently can be either a slice
object or an integer so new_data
will either be a list
or a single element. If it's a list
put it in the myList
container and return. Otherwise, if it's a single element, just pass that back.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.