Python 切片列表时是否复制对对象的引用?
Does Python copy references to objects when slicing a list?
当一个列表被切片时,对其内容的引用是否从原始列表中复制?我可以想象这可能没有必要,但我读到了相反的内容(mentioned in passing)。
这个问题很重要,例如下面的成语,在很长的情况下 my_list
:
for (first_elmt, second_elmt) in itertools.izip(my_list[:-1], my_list[1:]):
…
副本会耗尽内存,而且可能会耗费一些时间。我将 first_elmt
的索引与 xrange()
的索引进行了比较,在一个包含 1 亿个整数的列表中。切片方法实际上快了 20%,但似乎确实复制了引用(系统时间更长)。真的是这样吗?
PS:我现在意识到切片复制引用是很自然的:如果原始列表被修改,切片不会改变,所以它更容易实现切片复制原始列表的引用。不过,指向 CPython 实现的指针会很有趣。
切片将复制引用。如果你有一亿个东西的清单:
l = [object() for i in xrange(100000000)]
然后你切一片:
l2 = l[:-1]
l2
将拥有自己的 99,999,999 个指针的支持数组,而不是共享 l
的数组。然而,这些指针指向的对象没有被复制:
>>> l2[0] is l[0]
True
如果您想在不复制的情况下迭代列表中的重叠元素对,您可以zip
列表中的迭代器已经前进了一个位置:
second_items = iter(l)
next(second_items, None) # Avoid exception on empty input
for thing1, thing2 in itertools.izip(l, second_items):
whatever()
这利用了 zip
在任何输入迭代器停止时停止的事实。这可以扩展到您已经使用 itertools.tee
使用迭代器的情况
i1, i2 = itertools.tee(iterator)
next(i2, None)
for thing1, thing2 in itertools.izip(i1, i2):
whatever()
是的,slicing DO copy references,事实上,以这种方式复制列表是一个成语:newlst = lst[:]
.
当一个列表被切片时,对其内容的引用是否从原始列表中复制?我可以想象这可能没有必要,但我读到了相反的内容(mentioned in passing)。
这个问题很重要,例如下面的成语,在很长的情况下 my_list
:
for (first_elmt, second_elmt) in itertools.izip(my_list[:-1], my_list[1:]):
…
副本会耗尽内存,而且可能会耗费一些时间。我将 first_elmt
的索引与 xrange()
的索引进行了比较,在一个包含 1 亿个整数的列表中。切片方法实际上快了 20%,但似乎确实复制了引用(系统时间更长)。真的是这样吗?
PS:我现在意识到切片复制引用是很自然的:如果原始列表被修改,切片不会改变,所以它更容易实现切片复制原始列表的引用。不过,指向 CPython 实现的指针会很有趣。
切片将复制引用。如果你有一亿个东西的清单:
l = [object() for i in xrange(100000000)]
然后你切一片:
l2 = l[:-1]
l2
将拥有自己的 99,999,999 个指针的支持数组,而不是共享 l
的数组。然而,这些指针指向的对象没有被复制:
>>> l2[0] is l[0]
True
如果您想在不复制的情况下迭代列表中的重叠元素对,您可以zip
列表中的迭代器已经前进了一个位置:
second_items = iter(l)
next(second_items, None) # Avoid exception on empty input
for thing1, thing2 in itertools.izip(l, second_items):
whatever()
这利用了 zip
在任何输入迭代器停止时停止的事实。这可以扩展到您已经使用 itertools.tee
i1, i2 = itertools.tee(iterator)
next(i2, None)
for thing1, thing2 in itertools.izip(i1, i2):
whatever()
是的,slicing DO copy references,事实上,以这种方式复制列表是一个成语:newlst = lst[:]
.