虽然假设 Python 中的列表切片会创建对象的副本似乎是合乎逻辑的包含的对象,实际情况并非如此。相反,切片只是生成引用相同底层对象的新列表。这种识别对于理解 Python 的列表切片机制起着至关重要的作用。
考虑一个整数列表:
[1000 + 1, 1000 + 1, 1000 + 1]
尽管具有相同的值,这些对象是具有唯一 ID 的不同实体,如下所示:
map(id, [1000 + 1, 1000 + 1, 1000 + 1])
切片此列表可以保持这些引用的完整性:
b = [1000 + 1, 1000 + 1, 1000 + 1][1:3] map(id, b)
两个映射操作的输出是相同的,确认切片不会生成整数的新副本。
观察到类似的行为对于字典或列表等可变对象:
a = [{0: 'zero', 1: 'one'}, ['foo', 'bar']] map(id, a[1:])
切片仍然保留原始引用,表明切片是一种非复制操作。
for i in range(len(a)): x = a[:i] print('len: {}'.format(len(x))) print('size: {}'.format(sys.getsizeof(x)))虽然切片不涉及复制对象本身,但它会复制引用。在 64 位机器上每个引用占用 8 个字节,每个列表都有额外的 72 个字节的开销:
尽管如此,对于大多数应用程序来说,这种开销通常不是一个重要的问题。
虽然 Python 缺乏对视图的直接支持,但可以采用 numpy 数组等替代选项来实现内存优化。切片 numpy 数组创建与原始视图共享内存的视图,减少了开销,但引入了潜在的意外修改。
总之,Python 中的切片保留了对所包含对象的引用,避免了昂贵的复制操作。此机制通过确保切片反映对原始列表所做的更改来简化代码维护。虽然内存开销是一个考虑因素,但对于大多数实际应用程序来说,它通常不是主要问题。以上是Python 列表切片是否会创建对象的副本?的详细内容。更多信息请关注PHP中文网其他相关文章!