Python切片原理_切片对象实现说明

4次阅读

python切片是基于__getitem__和slice对象的机制:切片语法如a[1:5:2]被转为slice(1,5,2)传入,slice.indices(n)自动处理默认值、负索引与边界,确保安全可靠。

Python切片原理_切片对象实现说明

Python切片不是语法糖,而是一套有明确规则的机制:对象只要实现 __getitem__ 方法并能接收 slice 实例,就天然支持切片。核心在于 slice 对象的构造与解释。

切片字面量如何变成 slice 对象

当你写 a[1:5:2],Python 解析器会自动构造一个 slice(1, 5, 2) 对象,并把它作为参数传给 a.__getitem__()。等价于:

  • a.__getitem__(slice(1, 5, 2))
  • 省略写法如 a[:]slice(None, None, None)
  • a[::2]slice(None, None, 2)
  • a[3:]slice(3, None, None)

slice 对象的三个属性与默认行为

每个 slice 实例有 startstopstep 三个只读属性,值可能是 None。解释逻辑由被切对象自己决定,但内置类型(如 list、str)遵循统一规则:

  • step > 0(正向),默认 start = 0stop = len(obj)
  • step (反向),默认 <code>start = -1stop = -(len(obj)+1)
  • None 在不同位置含义不同,不能简单等同于 0 或长度
  • 负索引在计算前会先按 len(obj) + i 归一化(例如 -1 变成 len-1

自定义类支持切片的关键:正确处理 slice 参数

只需在 __getitem__ 中判断参数是否为 slice 实例,再手动解析逻辑。例如:

立即学习Python免费学习笔记(深入)”;

class MySeq:     def __init__(self, data):         self.data = data <pre class='brush:python;toolbar:false;'>def __getitem__(self, key):     if isinstance(key, slice):         # 手动处理 start/stop/step,默认值和负索引         start, stop, step = key.indices(len(self.data))         return [self.data[i] for i in range(start, stop, step)]     else:         return self.data[key]

注意:slice.indices(n) 是关键辅助方法——它把任意 slice 对象映射为三元组 (start, stop, step),其中所有值都是非负整数且已适配序列长度 n,避免手动处理边界和负索引错误。

为什么 indices() 比手动计算更可靠

直接用 key.start or 0 这类写法会出错,因为 None 和负数需结合长度重新计算。而 slice.indices(n) 内部已封装全部规则:

  • slice(1, None, 2).indices(10)(1, 10, 2)
  • slice(None, None, -1).indices(5)(4, -1, -1)
  • slice(-3, -1).indices(10)(7, 9, 1)

这是标准库推荐做法,也是 liststr 等底层实际使用的逻辑。

text=ZqhQzanResources