非继承实现含列表类:就地赋值元素为何触发IndexError?
用组合方式实现自定义列表类的就地赋值
错误原因
你触发的IndexError和原生列表的行为一致:当给空列表(或长度不足的列表)的超出范围索引赋值时,底层列表本身就不支持这种操作。比如直接运行l = []; l[0] = 'a'也会抛出同样的错误——你的组合类只是把这个错误透传了出来。
组合方式的解决方案
根据需求,有两种常见实现思路:
1. 自动扩展列表(赋值时填充默认值)
如果希望赋值超出当前长度的索引时,自动扩展列表并填充默认值(比如None),可以修改__setitem__方法,先检查索引范围,不足时扩展列表:
class MyOwnList(): def __init__(self, a_list): self.list = a_list.copy() # 复制输入列表,避免外部修改影响内部状态 def __getitem__(self, index): return self.list[index] def __setitem__(self, index, value): # 处理负索引 if isinstance(index, int): if index < 0: pos_index = len(self.list) + index if pos_index < 0: raise IndexError("list assignment index out of range") index = pos_index # 索引超出当前长度时,扩展列表 if index >= len(self.list): # 用None填充到目标索引位置 self.list += [None] * (index - len(self.list) + 1) # 处理切片赋值(原生逻辑自动兼容) self.list[index] = value # 测试 L2 = MyOwnList([]) L2[0] = "a" print(L2[0]) # 输出: a L2[2] = "b" print(L2.list) # 输出: ['a', None, 'b']
2. 保持原生列表的严格索引规则
如果想和原生列表行为完全一致,只允许在现有索引范围内赋值,那你的初始代码是正确的,但需要确保赋值前列表有足够长度。可以给类添加原生列表的常用方法(比如append、insert)来方便元素添加:
class MyOwnList(): def __init__(self, a_list): self.list = a_list.copy() def __getitem__(self, index): return self.list[index] def __setitem__(self, index, value): self.list[index] = value # 添加常用列表操作方法 def append(self, value): self.list.append(value) def insert(self, index, value): self.list.insert(index, value) def extend(self, iterable): self.list.extend(iterable) # 测试 L2 = MyOwnList([]) L2.append(None) # 先添加元素确保有索引0 L2[0] = "a" # 正常运行 print(L2[0]) # 输出: a
核心逻辑
组合方式的关键是正确包装底层列表的操作:你可以选择完全复刻原生列表的行为,或者根据需求扩展功能——本质都是通过操作self.list这个内部属性来实现,而不需要继承list或UserList。
内容的提问来源于stack exchange,提问作者progmatico
相关产品推荐
相关产品推荐

