切片操作是否总会分配新对象?其内存分配规则是什么?
Python切片的内存分配规则详解
嘿,这个问题问得特别到位!我当初刚摸Python的时候也被切片的对象创建逻辑绕晕过,咱们结合你的例子一步步理清楚。
先看你给出的代码片段:
>>> s = "hello world" >>> y = s[::] >>> id(s) 4507906480 >>> id(y) 4507906480 # 二者相同——未创建新对象 >>> z = s[:2] >>> z 'he' >>> id(z) 4507835488 # z是一个新对象
一、什么时候切片会返回原对象?
当你使用完整切片(也就是[::]或者简化的[:])时,对于字符串、元组这类不可变类型,Python会直接返回原对象的引用,不会分配新内存。这是Python的一个优化策略——既然切片结果和原对象完全一致,没必要浪费空间造个一模一样的新对象。
不过要注意:这个优化只针对不可变类型!如果是列表这种可变类型,lst[:]会创建一个新的列表对象(浅拷贝)。你可以自己测试:
>>> lst = [1,2,3] >>> lst2 = lst[:] >>> id(lst) == id(lst2) False
二、什么时候切片会创建新对象?
只要切片的结果和原对象不完全相同,Python就会分配新内存,生成新对象:
- 像你例子里的
s[:2],只截取了前2个字符,结果和原字符串不一样,必然要新建一个字符串对象。 - 其他场景比如:指定起始索引(
s[1:])、结束索引(s[:-1])、步长不为1(s[::2]),这些都会生成新的对象。
三、为什么不可变类型有这种特殊优化?
核心原因是不可变类型的内容无法被修改,返回原引用完全没有风险——不管你通过s还是y访问,内容都是固定的,不会出现修改一个影响另一个的情况。但可变类型就不行了,如果返回原引用,修改lst2的同时lst也会被改,这不符合切片拷贝的预期,所以必须创建新对象。
内容的提问来源于stack exchange,提问作者codeforester
相关产品推荐
相关产品推荐

