在关于素数的练习中,我发现
filter
本身不返回列表,我需要这样做:
list(filter())
获取该列表。
我做了两次练习,一次使用 for 循环:
def is_prime_for(n:init):
if n <=3:
return True
else:
m=list(range(2,n//2+1)) #+1 on the range for evade a bad result if 'n==4'
for i in m:
if n % i == 0:
return False
else:
return True
value = 864203
print(is_prime_for(value))
其他时间与
filter
和 lambda
:
def is_divisible(num1:float,num2:float):
if num1 % num2 == 0:
return True
else:
return False
def is_prime(num:int):
if list(filter(lambda x: is_divisible(num,x), list(range(2,num//2+1)))) != []:
return False
else:
return True
value = 864203 #Same prime number that i found on google
print(is_prime(value))
后来我重新使用高阶函数的代码,发现我的“紧凑”
filter
和lambda
函数需要比函数执行时间多一倍的时间,并且使用“False”数字(例如一个数字可以除以 2)。
我可以理解双倍时间,因为它会遍历列表两次而不是一次,但在“False”数字的情况下,我认为 filter() 会给我一个空列表,直到第一个数字出现,但这不是这种情况下,列表为“空”,直到过滤结束。
有谁知道一种方法来“更新”过滤的项目列表,而不是在过滤结束时一次列出?
这是我现在的代码,具有显示执行时间的高阶函数:
import time
def timeis(func): #Decorator that reports the execution time.
def wrap(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__, end-start)
return result
return wrap
def is_divisible(num1:float,num2:float):
if num1%num2 == 0:
return True
else:
return False
@timeis
def is_prime(num:int):
if list(filter(lambda x: is_divisible(num,x),list(range(2,num//2+1)))) != []: #+1 on the range for evade a bad result if 'n==4'
return False
else:
return True
@timeis
def is_prime_for(n : int = 2):
if n <= 3:
return True
else:
m = list(range(2,n//2+1))
for i in m:
if n%i == 0:
return False
else:
return True
value = 864203 #A prime number that i found on google
#print(is_prime(value)) #That is used for prove the value find on google for no "false" positives
is_prime(value)
is_prime_for(value)
这就是输出:
is_prime 0.06304740905761719
is_prime_for 0.02378678321838379
这里有一些需要改进的地方:
无需将
list
应用于 filter
的第二个参数的范围。 filter
只需要一个可迭代作为第二个参数,所以范围就可以了。
当目标是验证
list
不产生任何结果时,无需将 filter
应用于 filter
的结果。在这种情况下,您可以使用 any
而不是 filter
以下模式是需要摆脱的:
if <boolean-expression>:
return True
else:
return False
相反,只需返回布尔表达式的值。
通过使其内联执行模运算,您为
is_prime_for
提供了一点优势,而 is_prime
必须为此调用一个函数。为了有一个平等的竞争环境,is_prime
也应该排队执行该操作。
两种实现都可以通过将除数搜索限制为
n
的平方根来做得更好。任何更大的除数都会有一个更小的对应部分。例如,如果 n
有 n//2
作为除数,那么它也有 2 作为除数,所以不需要同时测试两者。
这给我们带来了这个版本的代码:
@timeis
def is_prime(num: int):
return any(num%x for x in range(2, int(num**0.5+1.01)))
进一步改进是可能的。