Python: 遍历 'list[a:b]' 是否会先复制该部分列表(可能代价高)?
当我从 list1
中的 start
到 stop
进行遍历时,就像这样:
for value in list1[start:stop]:
....
那么,Python 是不是会先复制那部分列表(就像执行 list2 = list1[:]
时那样)?如果列表很大,这样做可能会非常耗费资源!
如果在上面的例子中它没有复制,那这种情况总是这样吗?我需要在很大的(非常大的)列表的某些部分上,频繁地执行以下类型的循环:
for index, value in enumerate(list1[start:stop], start):
....
3 个回答
1
与其问这个问题,你不如试试神奇的ID方法。
>>> x=[1,2,3,4]
>>> id(x[1])
4971620
>>> id(x[1:][0]) #same as the original list
4971620
>>> id(x[2:3])
44327400
>>> id(x)
44408224
>>>
x[2:3]
实际上是创建了一个新列表,但这些元素仍然指向原来的列表。
2
是的。
这个表达式 list1[start:stop]
会创建一个新的列表,里面包含了指定范围内的元素。不过,它并不是在复制实际的数据,而是复制了一些指向这些数据的指针。所以,除非列表非常长,否则这种额外的开销通常不会影响太大。
8
list1[start:stop]
这个操作会创建一个新的列表,没错。这种情况总是如此,不管你是直接遍历这个结果,还是在中间加了个函数,或者在其他任何地方使用它(如果你用的是一种比较静态的语言,或者有复杂的类型推断,才能在简单的情况下优化这个操作)。
要注意的是,这个操作与遍历是无关的!遍历本身并不会复制,而列表切片操作即使你把结果丢掉了也会进行复制。
不过,它只复制了指针,所以如果你每次取的子列表都很小,你可能不会注意到有什么不同。如果子列表比较大,你可以选择遍历索引([x]range
)或者使用 itertools.islice
。不过,后者在开始时需要跳过 start
个项目,所以为了节省内存,你可能会付出较大的时间成本。前者虽然看起来不太好,但在效率上是最好的,尤其是当数据量很大时。