我有一个非常大的清单 假设我这样做(是的,我知道代码非常单调,但为了示例的缘故......):
n = (2**32)**2
for i in xrange(10**7)
li[i] = n
工作正常。但是:
for i in xrange(10**7)
li[i] = i**2
消耗大量内存。我不明白为什么会这样 - 存储大数字需要更多位,而在Java中,第二个选项确实更节省内存...
有没有人对此有解释?
答案 0 :(得分:17)
答案 1 :(得分:5)
在第一个示例中,您存储的是相同的整数len(arr)次。因此python只需要将整数存储在内存中一次,并将其引用为len(arr)次。
在第二个示例中,您存储的是len(arr)不同的整数。现在python必须为len(arr)整数分配存储空间,并在每个len(arr)插槽中引用它们。
答案 2 :(得分:3)
您只有一个变量n,但您创建了许多i ** 2.
Python会使用引用。每次执行array[i] = n
时,都会创建对n
值的新引用。注意,不要把变量告诉价值。但是,在第二种情况下,当您执行array[i] = i**2
时,您将创建一个新值,并引用此新值。这当然会占用更多的内存。
事实上,Python将继续重用相同的值,即使重新计算它也只是使用它。例如:
l = []
x = 2
for i in xrange(1000000):
l.append(x*2)
通常不会使用比
更多的内存l = []
x = 2
for i in xrange(1000000):
l.append(x)
然而,在
的情况下l = []
x = 2
for i in xrange(1000000):
l.append(i)
i的每个值都会得到一个引用,因此与其他示例相比,会占用大量内存。
(Alex在术语中指出了一些混淆。在python中有一个叫做数组的模块。这些类型的数组存储整数值,而不是像Pythons普通列表对象这样的对象的引用,但在其他方面表现相同。但是从第一个开始示例使用的值不能存储在这样的数组中,这种情况不太可能。
相反,问题很可能是使用单词数组,因为它在许多其他语言中使用,这与Pythons列表类型相同。)
答案 3 :(得分:0)
在两个示例中,arr[i]
都会引用对象,无论它是n
还是i * 2
的结果对象。
在第一个示例中,n
已经定义,因此它只需要引用,但在第二个示例中,它必须评估i * 2
,GC必须为此新结果对象分配空间,并且然后使用它的参考。