【问题标题】:Python giving a memory errorPython给出内存错误
【发布时间】:2014-09-29 10:29:29
【问题描述】:

大家好,我对 python 很陌生。我试图从一个在线编码网站解决这个问题

A=3,B=5
A = 3 , 6 , 9 , 12 ,15 ,18 等的表
B = 5 , 10 , 15 , 20 等的表
合并后:3、5、6、9、10、12、15、15、18、20等
删除重复项:3、5、6、9、10、12、15、18、20 等
对于 N= 2 ,超表的第二个元素是 5

问题是我可以得到有限范围的 A 和 B 的答案,但是当我为第 10^9 个元素这样做时,我得到了一个内存错误。

from array import *
import itertools
array1=[]
array2=[]
A=int(input())
B=int(input())
N=int(input())
for i in range(0,10**9):
    try:
        array1.append(i+1 * A)
    except MemoryError :
        break 

for j in range(0,10**9):
    try:
        array2.append(j+1 * B)
    except MemoryError :
        break
filter(None ,array1)
filter(None ,array2)
array3 = array1 + array2
array3 = sorted(set(array3))
print (array3[N])

回溯(最近一次通话最后一次):
文件“C:/Users/Clinton D/Desktop/supertables.py”,第 21 行,在
数组 3 = 数组 1 + 数组 2 内存错误

【问题讨论】:

  • 对于初学者,请尝试xrange...您正在制作一些大名单。
  • range 是 python 3 中的迭代器。
  • 当你只处理普通列表而没有数组时,为什么要从数组模块中导入 *? (或 itertools,就此而言,当你不使用它时?)
  • 太酷了。这是一个很好的决定。在这种情况下,只是您正在处理大量列表。
  • 您正在获得内存开销..10**9 x intsize,有关更多信息,请参阅其他答案:stackoverflow.com/a/14329864/764322

标签: python memory out-of-memory


【解决方案1】:

您不想提前创建整个列表(即,如果您只想找到第 N 个,为什么要创建所有这些值?)

你想做的是这样的:

def f(n):
    vals = (x for x in xrange(1, 10**9) if (x % 3 == 0) or (x % 5 == 0))
    for _ in xrange(n - 1):
        vals.next()
    return vals.next()

你只是在这里迭代,所以没有大的列表创建。

【讨论】:

    【解决方案2】:

    正如已经指出的那样,您在内存中制作了一些非常大的列表。我还发现您实际上期待 MemoryError 令人惊讶!您的部分问题将通过使用列表推导来解决,这些方法可以告诉 Python 如何构建列表,而无需使用 for 循环和追加。例如,前 100 个数字的平方的列表推导式可以写成:

    squares = [x*x for x in xrange(100)]
    

    列表推导由两部分组成:元素定义和应用它的可迭代集。在前面的示例中,x*x 是元素定义,xrange(100) 中的 x 是可迭代部分。

    现在回到你的问题。从您的代码中让我印象深刻的第二件事是使用数组模块,而无需特别需要它的任何内容。

    最后,使用 filter(None, [...]) 有助于消除每个计算结果为 False 的元素,对于数字来说,它是 0。在您的示例中,任何列表中都没有这样的元素,除非 A或 B 为 0。

    所以你的脚本应该是这样结束的:

    A = int(input())
    B = int(input())
    N = int(input())
    
    array1 = []
    array2 = []
    if A:
        array1 = [i * A for i in xrange(1, 10**7 + 1)]
    if B:
        array2 = [i * B for i in xrange(1, 10**7 + 1)]
    
    array1.extend(array2)
    del(array2)  # not entirely necessary, if you have 128GB RAM or more...
    array1 = sorted(set(array1))
    print array1[N-1]
    

    在我完全挂断计算机测试您的代码之前,我一直在想的事情是,您可以使用生成器来解决这个问题。我现在完全确定了。另外,为什么你需要 1 到 20 亿个元素?

    我认为您的问题与 Python 或内存不足无关,而是用于计算此值的糟糕算法——我只是稍微降低了它的糟糕程度。

    编辑:

    • @acushner 注意到正方形列表被简单地命名为列表,这可能会干扰 Python 内置列表。
    • 有些错别字。
    • 我发布了一个稍微不正确的脚本版本,现已修复。

    【讨论】:

    • 首先,您不应该将某个词命名为隐藏内置的词(在本例中为list)。其次,列表推导对内存管理没有任何作用。他们仍然会创建一个完整的列表。
    • 很好地发现了那里,尽管我必须说这是一个列表理解的例子,而不是代码本身。我试图向他介绍列表推导的概念,因为他说他是 Python 新手,而且从他的代码中,我知道他不了解它们。您是对的,理解不会改变整个列表在内存中的最终大小,但是它可以加速此类列表的创建,无论是运行时还是编程时。
    【解决方案3】:

    如果你真的需要使用这个大数据集,你应该使用pandasnumpy来处理它。

    但是,如果您尝试解决编码问题,请尝试使用较小的数据集来测试您的方法。无论如何,您可以考虑使用迭代器而不是列表,并使用 iterator.chain 来加入迭代器。

    from itertools import chain
    
    A=int(input())
    B=int(input())
    N=int(input())
    
    array_a = (i*A for i in range(10**4))
    array_b = (i*B for i in range(10**4))
    array_c = chain(array_a, array_b)
    c = sorted(set(array_c))
    
    print(c[N])
    

    【讨论】:

      猜你喜欢
      • 2012-04-29
      • 1970-01-01
      • 2020-04-13
      • 2014-05-11
      • 2013-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-04
      相关资源
      最近更新 更多