简体   繁体   English

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

[英]How do I optimize my Python code to perform my calculation using less memory?

I have put together the following code in order to determine if a number has an odd or even number of divisors. 我将以下代码组合在一起,以确定一个数的除数是奇数还是偶数。 The code works well with relatively small numbers but once a larger number like 9 digits is entered it hangs up. 该代码适用于相对较小的数字,但是一旦输入较大的数字(如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'

what can I do to make this more efficient? 我该怎么做才能提高效率?

Here's your problem: 这是您的问题:

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

This constructs a list, then constructs a set out of that list, then takes the length of the set. 这将构造一个列表,然后从该列表中构造一个集合,然后获取集合的长度。 You don't need to do any of that work ( range() , or xrange() for that matter, does not produce repeated objects, so we don't need the set, and sum() works on any iterable object, so you don't need the list either). 您不需要做任何工作( range()xrange()都不会产生重复的对象,因此我们不需要set,并且sum()可在任何可迭代的对象上使用,因此您也不需要该列表)。 While we're on the subject, divmod(n, x)[1] is just a very elaborate way of writing n % x , and consumes a little bit of extra memory to construct a tuple (which is immediately reclaimed because you throw the tuple away). 当我们讨论这个主题时, divmod(n, x)[1]只是编写n % x一种非常复杂的方法,并且会消耗一点额外的内存来构造一个元组(由于您抛出了元组)。 Here's the fixed version: 这是固定版本:

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

You do not need to test every possible divisor, testing up to sqrt(n) is enough. 您无需测试所有可能的除数,最多测试sqrt(n)就足够了。 This will make your function O(sqrt(n)) instead of O(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

In my benchmarks using python2 this is 1000 times faster than sum(1 for x in range(1, n + 1) if not n % x) with n = int(1e6) and 10000 times faster for 1e8. 在我使用python2的基准测试中,这比sum(1 for x in range(1, n + 1) if not n % x)快1000倍,而sum(1 for x in range(1, n + 1) if not n % x) n = int(1e6)比1e8快10000倍。 For 1e9 the latter code gave me a memory error , suggesting that the whole sequence is stored in memory before doing the sum because in python 2 range() returns a list and I should be using xrange() instead. 对于1e9 ,后面的代码给了我一个内存错误,这表明整个序列在进行求和之前先存储在内存中,因为在python 2中range()返回一个列表,而我应该使用xrange() For python3 range() is fine. 对于python3, range()很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM