Python List子类方法中,如何正确对self执行切片操作?
如何在List子类的方法中正确修改自身切片?
你遇到的核心问题是:在方法里直接给self赋值切片(self = self[i:])并不会修改原列表实例——这只是把方法内的局部变量self重新指向了一个新的切片对象,而原来的列表内容完全没变。
要正确修改子类化的List实例,你需要直接修改原列表的内容,而不是重新绑定self变量。这里有两种靠谱的实现方式:
方法一:使用切片赋值替换原列表内容
切片赋值self[:] = new_slice会直接修改原列表的内部元素,而不是创建新对象。针对你的trim方法,修改后的代码可以这样写:
import datetime as dt class BarList(list): """列表中的项始终按.date升序排列""" def trim(self, start: dt.datetime=None, end: dt.datetime=None): """移除`start`之前和`end`之后的所有bar""" # 处理start条件 if start: for i, bar in enumerate(self): if bar.date >= start: # 用切片赋值替换原列表内容 self[:] = self[i:] break # 处理end条件 if end: # 从后往前找第一个<=end的元素索引 for i in reversed(range(len(self))): if self[i].date <= end: self[:] = self[:i+1] break
方法二:先找到首尾索引,再一次性切片替换
如果列表很大,两次循环可能有点低效,你可以先找到符合条件的起始和结束索引,再一次性完成切片替换:
import datetime as dt class BarList(list): """列表中的项始终按.date升序排列""" def trim(self, start: dt.datetime=None, end: dt.datetime=None): """移除`start`之前和`end`之后的所有bar""" start_idx = 0 if start: for i, bar in enumerate(self): if bar.date >= start: start_idx = i break end_idx = len(self) if end: for i in reversed(range(len(self))): if self[i].date <= end: end_idx = i + 1 break # 一次性替换原列表内容 self[:] = self[start_idx:end_idx]
关键原理说明
self = self[i:]:只是改变了方法内self变量的指向,原列表实例不受影响。self[:] = self[i:]:属于原地修改,会把原列表的所有元素替换成切片后的元素,这样外部引用这个BarList实例的地方也能看到修改后的结果。
内容的提问来源于stack exchange,提问作者davidtgq
相关产品推荐
相关产品推荐

