python创建列表副本_在Python中切片列表而不生成副本

简短的回答

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

长话短说

可变和不可变值的测试

首先,让我们测试一下基本的声明。我们可以证明,即使在整数这样的不可变对象的情况下,也只复制引用。下面是三个不同的整数对象,每个对象都具有相同的值:>>> a = [1000 + 1, 1000 + 1, 1000 + 1]

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

[140502922988976, 140502922988952, 140502922988928]

切片它们时,引用保持不变。未创建新对象:>>> b = a[1:3]

>>> map(id, b)

[140502922988952, 140502922988928]

使用具有相同值的不同对象表明复制过程不需要interning——它只是直接复制引用。

使用可变值进行测试会得到相同的结果:>>> 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 Pinsonaultreminds us,这一开销加起来。整数对象本身并不是很大——它们比引用大三倍。所以这在绝对意义上为您节省了一些内存,但是渐进地说,能够将多个“视图”列表放在同一内存中可能是很好的。

使用视图节省内存

不幸的是,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时,这是一个折衷方案:减少计算机的工作量,增加程序员的工作量!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值