如何写更多Pythonic Code

时间:2012-07-14 00:29:53

标签: python python-2.7 idiomatic

我今天从官方网站上的教程开始学习python。

当阅读过滤器(函数,序列)时,我想要创建一个函数,如果一个数字是素数则返回使用它与过滤器。

notDividedBy = [2,3,4,5,6,7,8,9]

def prime(num):
    """True if num is prime, false otherwise"""    
    copy = notDividedBy[:]
    check = True
    if num in copy:
        copy.remove(num)
    for x in copy:
        if num % x == 0:
            check = False
            break
    return check

以上代码适用于shell。

我的问题是:既然我觉得虽然是一个解决方案,但它不是最优雅的解决方案,任何人都可以将此代码转换为更像python的东西吗?(更好的结构?更少的线?)

我相信这有助于我更好地理解语言的基础知识。

问题是,不要使用任何进口或任何东西,只需简单的员工。

4 个答案:

答案 0 :(得分:4)

创建许多列表副本并不是一种特别有效的方法。而是使用xrange()(Python 2.x)或range()(Python 3)迭代器。这是你可以实现素性测试的一种(天真)方式:

from math import sqrt

def isPrime(n):
    if n < 2: return False
    if n == 2: return True
    if not n % 2: return False #test if n is even

    #we've already remove all the even numbers, no need to test for 2
    #we only need to test up to sqrt(n), because any composite numbers can be
    #   factored into 2 values, at least one of which is < sqrt(n)
    for i in xrange(3, int(sqrt(n)) + 1, 2): 
        if not n % i:
            return False
    return True

答案 1 :(得分:4)

这个怎么样:

def is_prime(num):
    return not any(num%i == 0 for i in xrange(2,num/2+1))

for i in xrange(10):
    print i, is_prime(i)

<强>解释

从:

开始
(num%i==0 for i in xrange(2,num/2+1))

这是一个生成器表达式。我本可以使它成为列表理解:

[num%i==0 for i in xrange(2,num/2+1)]

列表理解等同于:

ll=[]
for i in xrange(2,num/2+1):
    ll.append(num%i==0)

生成器和列表推导之间的区别在于,生成器只在迭代它时放弃它的元素 - 而列表推导则预先计算所有值。无论如何,从上面的代码中,你可以看到表达式生成了一个True和False的序列。如果数字可以除以i,则为真,否则为假。如果我们生成一个所有假数的序列,我们知道我们有一个素数。

下一个技巧是内置any功能。它基本上搜索一个iterable并检查是否有任何值为True。一旦它到达True,它就会返回True。如果它到达iterable的末尾,则返回False。因此,如果整个序列为False(素数),则any将返回False,否则返回True。这对not_prime函数来说是完美的,但我们的函数是is_prime,因此我们只需要使用not运算符反转该结果。

使用生成器表达式的好处是它既简洁又简洁,但它允许any在检查每个值之前返回,这意味着只要它找到一个除以{{1}的数字},它返回而不是生成所有num个数字。

无论如何,我希望这个解释很有帮助。如果没有,请随时发表评论,我会尝试更好地解释。

答案 2 :(得分:0)

一件事,如果你打算以这种方式实施主要测试,没有理由使用辅助阵列

def prime(num):
    """True if num is prime, false otherwise"""    
    check = True
    #if num in copy:
    #    copy.remove(num)
    for x in range(2,x-1):
        if num % x == 0:
            check = False
            break
    return check

答案 3 :(得分:0)

这是使用过滤器(2)的2个班轮。

def prime(num):
    """True if num is prime, false otherwise"""
    if num < 2:
        return False
    return len(filter(lambda x: num % x == 0, range(2, num))) == 0