在 Python 中对列表进行切片而不生成副本

2025-01-03 08:40:00
admin
原创
114
摘要:问题描述:给定一个整数列表L,我需要生成所有子列表L[k:] for k in [0, len(L) - 1],而不生成副本。我如何在 Python 中实现这一点?使用缓冲区对象?解决方案 1:简短的回答切片列表不会生成列表中对象的副本;它只会复制对它们的引用。这就是所提问题的答案。详细答案测试可变和不可变值...

问题描述:

给定一个整数列表L,我需要生成所有子列表L[k:] for k in [0, len(L) - 1]而不生成副本。

我如何在 Python 中实现这一点?使用缓冲区对象?


解决方案 1:

简短的回答

切片列表不会生成列表中对象的副本;它只会复制对它们的引用。这就是所提问题的答案。

详细答案

测试可变和不可变值

首先,让我们测试一下基本说法。我们可以证明,即使是像整数这样的不可变对象,也只会复制引用。以下是三个不同的整数对象,每个对象都有相同的值:

>>> a = [1000 + 1, 1000 + 1, 1000 + 1]

它们具有相同的值,但是您可以看到它们是三个不同的对象,因为它们具有不同的ids:

>>> map(id, a)
[140502922988976, 140502922988952, 140502922988928]

当你对它们进行切片时,引用保持不变。没有创建新的对象:

>>> b = a[1:3]
>>> map(id, b)
[140502922988952, 140502922988928]

使用具有相同值的不同对象表明复制过程并不关心驻留——它只是直接复制引用。

使用可变值测试会得出相同的结果:

>>> a = [{0: 'zero', 1: 'one'}, ['foo', 'bar']]
>>> map(id, a)
[4380777000, 4380712040]
>>> map(id, a[1:]
... )
[4380712040]

检查剩余内存开销

当然,引用本身会被复制。在 64 位机器上,每个引用占用 8 个字节。每个列表都有自己的 72 个字节内存开销:

>>> for i in range(len(a)):
...     x = a[:i]
...     print('len: {}'.format(len(x)))
...     print('size: {}'.format(sys.getsizeof(x)))
... 
len: 0
size: 72
len: 1
size: 80
len: 2
size: 88

正如 Joe Pinsonault提醒我们的那样,这些开销加起来是相当可观的。而且整数对象本身并不是很大——它们比引用大三倍。因此,这在绝对意义上可以为您节省一些内存,但从渐近意义上讲,能够拥有多个作为同一内存“视图”的列表可能会更好。

使用视图节省内存

不幸的是,Python 没有提供简单的方法来生成“视图”到列表中的对象。或者我应该说“幸运”!这意味着您不必担心切片来自哪里;对原始切片的更改不会影响切片。总的来说,这使得推理程序的行为变得容易得多。

如果您确实想通过使用视图来节省内存,请考虑使用numpy数组。当您对numpy数组进行切片时,切片和原始数组之间共享内存:

>>> a = numpy.arange(3)
>>> a
array([0, 1, 2])
>>> b = a[1:3]
>>> b
array([1, 2])

a当我们修改并再次查看时会发生什么b

>>> a[2] = 1001
>>> b
array([   1, 1001])

但这意味着你必须确保当你修改一个对象时,你不会无意中修改另一个对象。这就是使用时的权衡numpy:计算机的工作量减少,程序员的工作量增加!

解决方案 2:

根据您正在做的事情,您可能能够使用islice

由于它通过迭代进行操作,因此它不会创建新的列表,而只是根据yield对原始列表范围的请求创建迭代器。

解决方案 3:

一个简单的替代方法islice是不迭代不需要的列表项:

def listslice(xs, *args):
    for i in range(len(xs))[slice(*args)]:
        yield xs[i]

用法:

>>> xs = [0, 2, 4, 6, 8, 10]

>>> for x in listslice(xs, 2, 4):
...     print(x)
4
6

解决方案 4:

一般来说,列表切片是最好的选择。

以下是一个快速的性能比较:

from timeit import timeit
from itertools import islice

for size in (10**4, 10**5, 10**6):
    L = list(range(size))
    S = size // 2
    def sum_slice(): return sum(L[S:])
    def sum_islice(): return sum(islice(L, S, None))
    def sum_for(): return sum(L[i] for i in range(S, len(L)))

    assert sum_slice() == sum_islice()
    assert sum_slice() == sum_for()

    for method in (sum_slice, sum_islice, sum_for):
        print(f'Size={size}, method={method.__name__}, time={timeit(method, number=1000)} ms')

结果:

Size=10000,   method=sum_slice,  time=0.0298 ms
Size=10000,   method=sum_islice, time=0.0449 ms
Size=10000,   method=sum_for,    time=0.2500 ms
Size=100000,  method=sum_slice,  time=0.3262 ms
Size=100000,  method=sum_islice, time=0.4492 ms
Size=100000,  method=sum_for,    time=2.4849 ms
Size=1000000, method=sum_slice,  time=5.4092 ms
Size=1000000, method=sum_islice, time=5.1139 ms
Size=1000000, method=sum_for,    time=26.198 ms

解决方案 5:

我编写了一个ListView类,可以避免复制列表的主干:

https://gist.github.com/3noch/b5f3175cfe39aea71ca4d07469570047

它支持嵌套切片,以便您可以继续切片视图以获得更窄的视图。例如:ListView(list(range(10)))[4:][2:][1] == 7

请注意,这还没有完全完成,当底层列表与测试套件一起发生变化时,需要进行更多的错误检查。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3892  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2717  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   52  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   54  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   49  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用