直接返回 slice 对象会报错,因为 python 期望 getitem 返回可迭代序列而非 slice;需用 isinstance(idx, slice) 判断类型,对切片调用 idx.indices(len(self)) 获取归一化索引再构造结果。

为什么直接返回 slice 对象会报错
当你在 __getitem__ 中收到一个 slice 实例(比如 obj[1:5:2]),Python 期望你返回一个**可迭代的序列对象**(如 list、tuple 或自定义容器),而不是原样返回 slice。否则会触发 TypeError: 'slice' object is not iterable —— 这是因为切片语法最终要被 for 循环或 list() 等消费,而 slice 本身不可迭代。
__getitem__ 中如何区分 int 和 slice
必须显式判断参数类型,不能假设只收整数索引。常见错误是写成 def __getitem__(self, idx): return self.data[idx],这在遇到 slice 时直接转发给底层容器(如 list)可能“碰巧”工作,但一旦底层不支持(比如用 dict 存数据)或需自定义逻辑就会崩。
- 用
isinstance(idx, slice)判断是否为切片 - 用
idx.start、idx.stop、idx.step提取边界值;三者都可能是None,需按 Python 规则补默认值(如start=0、stop=len(self)、step=1) - 手动计算索引范围,再逐个调用
self[i]或批量构造结果(注意:不要直接用range()遍历负 step,slice.indices(len)更安全)
用 slice.indices() 正确处理负索引和省略边界
手动算 start/stop 容易出错,尤其涉及负数或 None。正确做法是调用 idx.indices(len(self)),它返回一个三元组 (start, stop, step),已按当前序列长度归一化为非负有效值。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
def __getitem__(self, idx):
if isinstance(idx, slice):
start, stop, step = idx.indices(len(self))
return [self[i] for i in range(start, stop, step)]
else:
# 处理单个 int 索引
if idx <h3>返回值类型要和预期一致</h3><p>如果用户写 <code>mylist[2:4]</code>,直觉上希望得到一个同类型的对象(比如还是 <code>MyList</code> 实例),而不是 <code>list</code>。但 Python 不强制要求——是否返回新实例取决于你的设计目标:</p>
- 若想保持类型,构造并返回
self.__class__(...),传入切片后的数据 - 若只是轻量包装(如只读视图),返回
list更简单,但要注意用户调用.append()会失败 - 性能敏感场景避免重复拷贝:可用生成器表达式或自定义惰性切片类,但必须确保支持
len()和迭代
最常被忽略的是:没实现 __len__ 就用 slice.indices(len(self)),会导致 AttributeError —— 记得补上。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










