切片列表时,Python是否复制对对象的引用? [英] Does Python copy references to objects when slicing a list?

查看:139
本文介绍了切片列表时,Python是否复制对对象的引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

切片列表时,是否从原始列表复制了对其内容的引用?我可以想象这可能不是必需的,但我读到相反的内容(顺便提及)。

When a list is sliced, are the references to its contents copied from the original list? I can imagine that this may not be necessary, but I read the opposite (mentioned in passing).

例如,对于很长的 my_list 情况,该问题对于以下惯用法很重要:

This question matters for instance for the following idiom, in the case of a very long my_list:

for (first_elmt, second_elmt) in itertools.izip(my_list[:-1], my_list[1:]):
    …

一个副本将同时占用内存和大概时间。我将循环索引 first_elmt xrange()进行比较,结果是一个1亿整数列表。切片方法实际上快了20%,但似乎确实复制了引用(系统时间更长)。

A copy would use up both memory and, presumably, some time. I compared to looping over the index of first_elmt with xrange(), on a list of 100 million integers. The slicing approach is actually 20% faster, but does seem to copy references (the system time is longer). Is this indeed the case?

PS :我现在意识到切片复制引用是很自然的:如果原始列表被修改,分片不会更改,因此让分片的实现更容易复制原始列表的引用。不过,指向CPython实现的指针会很有趣。

PS: I now realize that it is quite natural that slices copy the references: if the original list is modified, the slice does not change, so it is easier to have the implementation of the slice copy the references of the original list. A pointer to the CPython implementation would be interesting, though.

推荐答案

切片将复制引用。如果您有一亿个事物的列表:

Slicing will copy the references. If you have a list of 100 million things:

l = [object() for i in xrange(100000000)]

,然后切成薄片:

l2 = l[:-1]

l2 将拥有自己的99,999,999个指针的后备数组,而不是共享 l 的数组。但是,不会复制这些指针引用的对象。

l2 will have its own backing array of 99,999,999 pointers, rather than sharing l's array. However, the objects those pointers refer to are not copied:

>>> l2[0] is l[0]
True

如果要迭代重叠对列表中的两个元素而无需复制,则可以使用迭代器将列表 zip 压缩到一个位置:

If you want to iterate over overlapping pairs of elements of a list without making a copy, you can zip the list with an iterator that has been advanced one position:

second_items = iter(l)
next(second_items, None) # Avoid exception on empty input
for thing1, thing2 in itertools.izip(l, second_items):
    whatever()

这利用了<$ c $当任何输入迭代器停止时,c> zip 停止。可以将其扩展到已经使用 itertools.tee

This takes advantage of the fact that zip stops when any input iterator stops. This can be extended to cases where you're already working with an iterator using itertools.tee

i1, i2 = itertools.tee(iterator)
next(i2, None)
for thing1, thing2 in itertools.izip(i1, i2):
    whatever()

这篇关于切片列表时,Python是否复制对对象的引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆