Python自定义类如何实现下标访问返回可变视图,类numpy数组修改同步
你当前的实现输出False,核心原因是Python原生列表的切片操作会生成新的独立列表,你在__getitem__中返回的Custom(items[key])实际持有了切片得到的新列表,修改这个新列表自然不会同步到原实例的列表。
要实现类似numpy数组的视图效果,核心思路是:所有Custom实例共享同一份底层存储的列表,每个实例仅记录自己对应数据的偏移量和长度,所有读写操作都基于偏移量映射到原始列表的对应位置,不做数据拷贝。
完整实现代码
class ListView: """支持视图逻辑的列表代理,兼容.items[]读写操作""" def __init__(self, custom_inst): self.inst = custom_inst def __getitem__(self, key): if isinstance(key, int): if key < 0: key += self.inst._length if not 0 <= key < self.inst._length: raise IndexError("list index out of range") return self.inst._data[self.inst._offset + key] elif isinstance(key, slice): return self.inst[key].items def __setitem__(self, key, value): if isinstance(key, int): if key < 0: key += self.inst._length if not 0 <= key < self.inst._length: raise IndexError("list assignment index out of range") self.inst._data[self.inst._offset + key] = value class Custom: def __init__(self, items, offset=0, length=None): # 所有实例共享的原始数据列表,仅初始化时实际存储 self._data = items # 当前视图的起始偏移和长度 self._offset = offset self._length = length if length is not None else len(items) - offset # 绑定items代理,兼容原代码的.items[]写法 self.items = ListView(self) def __getitem__(self, key): if isinstance(key, int): # 单个元素访问直接返回对应值 if key < 0: key += self._length if not 0 <= key < self._length: raise IndexError("list index out of range") return self._data[self._offset + key] elif isinstance(key, slice): start, stop, step = key.indices(self._length) # 简单实现仅支持步长为1的切片生成视图,非步长1可按需扩展 if step != 1: raise NotImplementedError("Only step=1 slice is supported for view") # 直接共享原始_data,仅传递偏移和长度,不拷贝数据 return Custom(self._data, self._offset + start, stop - start)
测试效果
运行你提供的测试代码:
custom = Custom([1, 2, 3, 4]) view = custom[0:2] view.items[0] = 0 print(custom.items[0] == 0)
输出结果为True,符合预期。
补充说明
如果你不需要兼容view.items[0] = 0的写法,直接通过实例本身做下标操作(即view[0] = 0),可以省略ListView代理类,在Custom中补充__setitem__方法即可,代码会更简洁。
内容的提问来源于stack exchange,提问作者Ramen
相关产品推荐
相关产品推荐

