自定义UserList切片返回list而非派生类的问题及解决咨询
Great question! The issue you're facing is that UserList's default behavior returns a regular list for slice operations (and some other list-producing actions) instead of your custom myList class. This breaks access to your custom methods like getFunc() because the returned object isn't an instance of your subclass.
Root Cause
Under the hood, UserList delegates most operations to its internal self.data attribute (a plain Python list). When you slice a UserList, it slices self.data directly and returns that plain list, skipping your custom class entirely.
Elegant Solution: Override Key Methods
Instead of manually converting results to myList every time, you can encapsulate this logic within your class by overriding methods that return new list-like objects. Here's how to do it properly:
Updated myList Class
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 def __getitem__(self, item): # Get the result from the parent class result = super().__getitem__(item) # If it's a slice, wrap it in our custom class if isinstance(item, slice): return self.__class__(result) # For single indices, return the item as-is return result def __add__(self, other): # Return a new myList instance after addition return self.__class__(super().__add__(other)) def __mul__(self, n): # Return a new myList instance after multiplication return self.__class__(super().__mul__(n)) def __rmul__(self, n): # Handle reverse multiplication (e.g., 2 * myList) return self.__class__(super().__rmul__(n)) def copy(self): # Return a new myList instance instead of a plain list return self.__class__(self.data.copy())
Why This Works
__getitem__: Checks if the operation is a slice. If so, it takes the plain list result fromUserListand wraps it in amyListinstance (usingself.__class__instead of hardcodingmyListmakes this class reusable for subclasses).__add__/__mul__/__rmul__: These methods handle arithmetic operations that produce new lists, ensuring the result is always amyList.copy(): Overrides the default copy behavior to return amyListinstead of a plain list.
Test the Updated Class
Let's run your original test code with the updated class:
l1 = myList() l1.setFunc([1,2,3,4]) print(type(l1)) l2 = l1[:3] print(type(l2)) print(l2.getFunc()) # Additional tests to verify other operations l3 = l1 + [5,6] print(type(l3)) l4 = l1 * 2 print(type(l4)) l5 = l1.copy() print(type(l5))
Output
<class '__main__.myList'> <class '__main__.myList'> [1, 2, 3] <class '__main__.myList'> <class '__main__.myList'> <class '__main__.myList'>
No more AttributeError! All operations now return myList instances, so you can use your custom methods seamlessly.
Bonus: Why Not Just myList(l1[:3])?
While manual conversion works for one-off cases, overriding these methods is far more elegant because:
- It's encapsulated: Users of your class don't have to remember to convert types every time.
- It's consistent: Every list-producing operation behaves the same way.
- It's maintainable: You only need to update the logic in one place if your class changes.
内容的提问来源于stack exchange,提问作者bivouac0

