Python 我的主要过滤代码有什么问题?它赢了';不要返回正确的列表

Python 我的主要过滤代码有什么问题?它赢了';不要返回正确的列表,python,python-3.x,recursion,primes,Python,Python 3.x,Recursion,Primes,我编写了一个函数filter\u primes,它应该(恰当地)从给定列表中过滤出素数,并输出一个新的素数列表。当我运行这个示例时,我得到了>>[9]。 我的脑子乱七八糟。有人能给我指出正确的方向吗 n = 2 def is_prime(num): global n if num%n != 0 and n<num: n = n + 1 is_prime(num) elif n == num: return True else: return

我编写了一个函数
filter\u primes
,它应该(恰当地)从给定列表中过滤出素数,并输出一个新的素数列表。当我运行这个示例时,我得到了>>[9]。
我的脑子乱七八糟。有人能给我指出正确的方向吗

n = 2

def is_prime(num):
  global n
  if num%n != 0 and n<num:
    n = n + 1
    is_prime(num)
  elif n == num:
    return True
  else:
    return False

def filter_primes(list1):
  list2 = []
  for i in list1:
    if is_prime(i):
      list2.append(i)

  print(list2)


filter_primes([7, 9, 3, 9, 10, 11, 27])
n=2
def是_prime(num):
全球n

如果数量为%n!=0和n问题出在
is_prime
函数中。由于您是以递归方式执行此操作,因此希望将其分为:

  • 处理基本情况:
  • 你会发现一个
    n
    平均除以
    num
    ,那么
    num
    就不是素数了
  • 最后得到的
    n
    大于
    num
    ,则
    num
    为素数
  • 否则,使用
    n+1
    递归调用函数,并
    返回该值
使用全局n(每次使用新的较大值时都会被覆盖)的一种方法是使用is_prime(n有一个默认的起始值) 比如说,

def is_prime(num, n=2):
  if n >= num:  # This could be made into sqrt(num) if you're trying to optimize this
      return True
  if num % n == 0:
      return False
  return is_prime(num, n+1)

问题出在
is_prime
函数中。由于您是以递归方式执行此操作,因此希望将其分为:

  • 处理基本情况:
  • 你会发现一个
    n
    平均除以
    num
    ,那么
    num
    就不是素数了
  • 最后得到的
    n
    大于
    num
    ,则
    num
    为素数
  • 否则,使用
    n+1
    递归调用函数,并
    返回该值
使用全局n(每次使用新的较大值时都会被覆盖)的一种方法是使用is_prime(n有一个默认的起始值) 比如说,

def is_prime(num, n=2):
  if n >= num:  # This could be made into sqrt(num) if you're trying to optimize this
      return True
  if num % n == 0:
      return False
  return is_prime(num, n+1)

我解决这个问题的方法是在IDE(IntelliJ)中打开代码,然后使用集成的调试器逐行遍历代码。这将帮助你想象正在发生的事情。否则,请尝试打印出函数内的变量

第一个问题是您正在使用
global n
。这对于第一个数字
7
,效果非常好,但是对于第二个数字
9
,此数字不会被重置。因此,
is_prime(9)
只针对
8
的除法进行测试(这就是它返回true的原因)

这可能在循环中完成,而不是使用递归,但由于您使用的是递归,
n
(作为内部状态)可以通过将其作为带有默认值的函数参数传递来处理。这将为n的每个顶级调用重置n

另外,当您递归调用
is_prime()
时,您需要
return is_prime()
以确保当您将原始调用方放回到堆栈底部时,从堆栈顶部返回的布尔值会返回

您的代码意外地为
is_prime(9)
工作,因为您的逻辑只测试了8,因此可以返回而不重复

以下是工作代码:

def为素数(num,n=2):
如果数量为%n!=0和n
此外,您可能会发现阅读一下
素数搜索算法
也很有趣

一些简单的优化:

  • 除2外,所有素数都是奇数(因此可以立即返回False)
  • 埃拉托斯烯的筛进一步扩大了这一范围
  • 从技术上讲,您只需搜索到
    sqrt(num)
  • 请阅读
    备忘录(也称为动态编程),因为您可以缓存以前函数调用的结果
  • 为您的函数添加python类型的提示和编写文档(一个月后返回代码时,您未来的自己会感谢您)
考虑一个新用例:

  • 生成整个素数序列(您将在此处开始注意性能问题)
  • 在IDE中添加计时器或使用探查器。比较代码运行的速度,尤其是对于大的数字。这些建议的优化是否加快了速度

    • 我解决这个问题的方法是在IDE(IntelliJ)中打开代码,然后使用集成的调试器逐行检查代码。这将帮助你想象正在发生的事情。否则,请尝试打印出函数内的变量

      第一个问题是您正在使用
      global n
      。这对于第一个数字
      7
      ,效果非常好,但是对于第二个数字
      9
      ,此数字不会被重置。因此,
      is_prime(9)
      只针对
      8
      的除法进行测试(这就是它返回true的原因)

      这可能在循环中完成,而不是使用递归,但由于您使用的是递归,
      n
      (作为内部状态)可以通过将其作为带有默认值的函数参数传递来处理。这将为n的每个顶级调用重置n

      另外,当您递归调用
      is_prime()
      时,您需要
      return is_prime()
      以确保当您将原始调用方放回到堆栈底部时,从堆栈顶部返回的布尔值会返回

      您的代码意外地为
      is_prime(9)
      工作,因为您的逻辑只测试了8,因此可以返回而不重复

      以下是工作代码:

      def为素数(num,n=2):
      如果数量为%n!=0和n