python切片是浅拷贝:创建新容器但元素引用原对象内存地址,对可变嵌套对象修改会影响原序列;时间与空间复杂度均为o(k),字符串有优化,需依场景选择切片、islice或deepcopy。

Python切片不是简单的“复制”或“引用”,而是一种浅拷贝(shallow copy)行为——它创建新对象,但其中的元素仍指向原对象中的相同内存地址(对不可变对象无影响,对可变对象需特别注意)。
切片到底做了什么?
当你执行 a[1:4] 时,Python 会:
- 分配一块新的内存,构建一个同类型的新容器(如 list、str、tuple)
- 将原序列中对应位置的引用逐个复制过去(不是深拷贝)
- 对不可变对象(如 int、str、tuple),这等价于“值复制”,因为它们无法被就地修改
- 对可变对象(如嵌套的 list、dict),新列表里的子对象和原列表共享同一份数据
验证是否为浅拷贝
看这个例子:
original = [[1], [2, 3], 4] sliced = original[0:2] # [[1], [2, 3]] <p>sliced[0].append(99) # 修改子列表 print(original) # [[1, 99], [2, 3], 4] ← 原列表也被改了! print(sliced) # [[1, 99], [2, 3]]
说明切片后,sliced[0] 和 original[0] 指向同一个子列表对象。
立即学习“Python免费学习笔记(深入)”;
性能表现:快,但有代价
切片时间复杂度为 O(k),k 是切片长度;空间复杂度也是 O(k),因为要分配新容器。常见情况:
-
小切片(如
lst[:3]):开销极小,几乎可忽略 -
大切片(如
big_list[1000:90000]):触发大量内存分配与引用复制,可能成为瓶颈 - 字符串切片:CPython 中做了优化(使用引用计数+偏移,不立即拷贝内容),所以非常快,但语义上仍是新对象
-
避免重复切片:比如循环中写
data[i:i+10],应考虑用itertools.islice或预计算边界
什么时候该用切片?什么时候不该?
✅ 推荐用切片:
- 提取子序列、翻转(
lst[::-1])、步进取值(lst[::2]) - 函数参数传递时需隔离输入(防止被意外修改)——但仅限不含可变嵌套的情况
⚠️ 谨慎或换方案:
- 需要真正独立副本(含嵌套可变对象)→ 改用
copy.deepcopy() - 只读遍历大序列某段 → 用
itertools.islice(iterable, start, stop),避免内存占用 - 频繁截取且原数据不变 → 可考虑用
memoryview(针对 bytes/bytearray)或 NumPy 切片(支持视图机制)











