如何优化我的Python代码以使用更少的内存执行计算?

时间:2016-04-08 04:27:48

标签: python math optimization numbers

我已将以下代码放在一起,以确定数字是否具有奇数或偶数的除数。该代码适用于相对较小的数字,但一旦输入更大的数字,如9位数,它就会挂断。

def divisors(n):
    num = len(set([x for x in range(1,n+1) if not divmod(n,x)[1]]))
    if (num != 0 and num % 2 == 0):
        return 'even'
    else:
        return 'odd'

我该怎么做才能提高效率呢?

2 个答案:

答案 0 :(得分:2)

这是你的问题:

num = len(set([x for x in range(1,n+1) if not divmod(n,x)[1]]))

这构造一个列表,然后构造该列表的一个集合,然后获取集合的长度。您无需执行任何相关操作(range()xrange(),因此不会生成重复的对象,因此我们不需要该集合,sum()可以正常工作在任何可迭代对象上,所以你不需要列表)。当我们讨论这个主题时,divmod(n, x)[1]只是一种非常精细的编写n % x的方式,并且消耗了一些额外的内存来构造一个元组(由于你把元组扔掉而立即回收) )。这是固定版本:

num = sum(1 for x in xrange(1,n+1) if not n % x)

答案 1 :(得分:2)

您不需要测试每个可能的除数,测试到sqrt(n)就足够了。这将使您的函数O(sqrt(n))而不是O(n)。

import math

def num_divisors(n):
    sqrt = math.sqrt(n)
    upper = int(sqrt)
    num = sum(1 for x in range(1, upper + 1) if not n % x)
    num *= 2
    if upper == sqrt and num != 0:
        num -= 1
    return num

在使用python2的基准测试中,这比使用sum(1 for x in range(1, n + 1) if not n % x)的{​​{1}}快1000倍,而对于1e8则快10000倍。对于n = int(1e6),后面的代码给了我一个内存错误,暗示整个序列在执行求和之前存储在内存中因为在python 2中1e9返回一个列表而我应该使用range()代替。对于python3 xrange()没问题。