Python会尽可能重用列表吗?
我的意思是,如果你用一个形状相同的列表去覆盖一个列表,它会保留第一个列表吗?比如:
point = [1, 2]
for x in xrange(10000000):
point = [x, x + 1]
在每次循环中,Python会重新使用point = [1, 2]
这个列表,只是把point[0]
和point[1]
的值更新为x
和x + 1
吗?还是说每次循环都会创建一个新列表,然后把旧的丢掉?换句话说,这样做的性能和
point = [1, 2]
for x in xrange(10000000):
point[0] = x
point[1] = x + 1
我只是好奇Python在背后是否会进行这种优化。
编辑:除了大家下面说的,我也出于好奇做了一些基准测试。
在我那台老旧的ThinkPad Core2Duo上:
point = [1, 2]
for x in xrange(10000000):
point = [x, x + 1]
# Result:
# real 0m6.164s
point = [1, 2]
for x in xrange(10000000):
point[0] = x
point[1] = x + 1
# Result:
# real 0m3.623s
5 个回答
这一行 point = [x, x + 1]
主要做了两件事:
[x, x + 1]
创建了一个新的列表。在这个时候,Python 并不知道你会用这个列表point
来做什么,或者你接下来会怎么处理它。point = ...
将新创建的列表赋值给之前的列表,同时释放掉之前的列表。
不,Python在写 point = [x,x+1]
时不会重复使用列表。顺便说一下,你可以进行就地赋值,这样列表就会保持不变。
举个例子:
point = [1,2]
for x in range(5): # Reusing point list
point[:] = [x,x+1]
for x in range(5): # Creating new list
point = [x,x+1]
正如@wim所说,你可以用 id(point)
来检查内存地址。
不,情况并不是这样。当你写 point = [1, 2]
的时候,实际上是Python创建了一个列表 [1, 2]
,然后让 point
指向这个列表在内存中的地址。接着,当你写 point = [x, x+1]
时,Python又创建了一个全新的列表,并且简单地把 point
指向这个新列表的内存地址。原来的列表 [1, 2]
其实还是在内存里的,只是你无法再访问它,之后Python会自动把它清理掉。
你可以这样做:
point = [1, 2]
b = point
point = [3, 4]
print(b == point)
point2= [1, 2]
c = point2
point2[0] = 3
print(c == point2)
这个输出能说明一切。
加上这个 print
来找出你的答案:
point = [1, 2]
for x in xrange(10000000):
point = [x, x + 1]
print(id(point))
这样做可以告诉你 point
的内存位置,从而判断它是否在重复使用这个实例,或者让它被垃圾回收。
不,CPython 不会重用列表对象。那行代码 point = [x, x + 1]
会创建一个全新的对象,如果 point
是唯一指向之前那个对象的引用,那么之前的对象就会被销毁。
不过,Python 确实会重用 tuple
对象(有个上限),因为在正常运行 Python 程序时,Python 内部会创建和销毁很多元组。想了解更多,可以查看 元组在 CPython 中是如何实现的?