为什么这个for循环在Python中占用太多时间和空间

时间:2015-11-10 08:39:17

标签: python loops

我是Python的初学者。我正在运行for循环来计算两个列表中的值。假设我有两个列表,如

import random
random.seed(9001)
help=[random.randint(0,9) for p in range(0,100000)]
out=[random.randint(0,9) for p in range(0,100000)]

我想计算[abs(i - 0.77*j) for i in help for j in out]

的总和

所以我使用了以下代码。

diff = [abs(i - 0.77*j) for i in help for j in out]
print sum(diff)

当我尝试运行此代码时,需要花费太多时间和硬盘空间。为什么我有这个问题?

有什么更好的方法来计算我想要获得的值?

2 个答案:

答案 0 :(得分:4)

您可以使用生成器表达式来避免分配大列表(见下文)

diff = (abs(i - 0.77*j) for i in help for j in out)
print sum(diff)

然而

您可能需要考虑真的是否需要sum([abs(i - 0.77*j) for i in help for j in out])

此等式解释了list s:

之间的关系
len(diff)=len(out)*len(help)

在您的情况下, 10e5 * 10e5 10e10 = 400-800 GigaByte ,具体取决于您int的时长。这不是适合你的磁盘,即使使用发电机也很可能需要花费太多时间。

您很可能只想将out[0]help[0]out[1]help[1]相乘,依此类推。然后,您可以使用zip或其生成器链接izip来快速实现此目的:

from itertools import izip

sum(abs(i - 0.77*j) for i,j in izip(help,out))

如果您不打算重复使用helpout,则可以编写最快的变体:

from itertools import izip

sum(abs(i - 0.77*j) for i,j in izip(xrange(100000),xrange(100000))

一些测量:

In [1]: import random
In [2]: random.seed(9001)
In [3]: help=[random.randint(0,9) for p in range(0,100000)]
In [4]: out=[random.randint(0,9) for p in range(0,100000)]

<强>拉链

In [8]: %timeit sum(abs(i - 0.77*j) for i,j in zip(help,out))
10 loops, best of 3: 62.9 ms per loop

<强> izip

In [11]: In [8]: %timeit sum(abs(i - 0.77*j) for i,j in izip(help,out))
10 loops, best of 3: 50.8 ms per loop

<强> x范围

In [17]: help=xrange(10**5)

In [18]: out=xrange(10**5)

In [19]: %timeit sum(abs(i - 0.77*j) for i,j in izip(help,out))         
10 loops, best of 3: 34.5 ms per loop

最初的想法

In [21]: help=range(1000)
In [22]: out=range(1000)    
In [24]: %timeit sum([abs(i - 0.77*j) for i in help for j in out])
1 loops, best of 3: 316 ms per loop

10e4*10e4仍在计算中。

<强>更新

In [25]: help=range(10000)
In [26]: out=range(10000) 
In [27]: %timeit sum([abs(i - 0.77*j) for i in help for j in out])
1 loops, best of 3: 2min 46s per loop

10e3**210e4**2的增长因子 553 ,这意味着10e5**2预计需要25h30m。

答案 1 :(得分:0)

[abs(i - 0.77*j) for i in help for j in out]将是一个包含100000²=10¹⁰整数的数组。这是37Gb的数据。您确定不想计算以下数组吗?

[abs(i - 0.77*j) for i, j in zip(help, out)]

这将是一个包含100000个元素的数组。

Here是关于zip的文档。