neolee / wop-community

29 stars 19 forks source link

大作业疑问 #218

Closed Wangbicong closed 4 years ago

Wangbicong commented 4 years ago

from math import sqrt

class primes:

def __init__(self):#定义初始值为1
    self.base = 1

def __iter__(self):
    return self

def __next__(self):#寻找下一个素数并返回
    self.base += 1
    if self.base in (2, 3):
        return self.base

    for i in range(2, int(sqrt(self.base))+1):
        if self.base % i == 0:
            break

    return self.base

老师,我用这种写法输出前10个素数,结果输出2-11,感觉是for循环的问题。

neolee commented 4 years ago

首先,好好阅读下 https://github.com/neolee/wop-community 学习如何贴代码。

然后重新看一下今天课上讲的 mk1 的思路,看看和你的实现区别在哪里。

Wangbicong commented 4 years ago

贴代码:

from math import sqrt
from itertools import islice

class primes:

    def __init__(self):#定义初始值为1
        self.base = 1

    def __iter__(self):
        return self

    def __next__(self):#寻找下一个素数并返回
        n = self.base + 1#从2开始寻找
        if n in (2, 3):#如果是2,保存到self.base并返回
            self.base = n
            return self.base#return之后退出__next__方法

        for i in range(2, int(sqrt(self.base))+1):#如果不是2,执行这个方法,判断是否是素数,如果不是,break,跳出for循环
            if n % i == 0:
                break

        self.base = n #如果是素数,保存到self.base并返回       
        return self.base#return之后退出__next__方法

f = primes()
for n in islice(f, 0, 10):
    print(n)

老师,mk1 的方法实现我可以理解,先写一个判断是不是素数的方法,然后写一个next迭代器来寻找下一个素数并返回。我这种写法是把判断是不是素数的逻辑写道迭代器里,本质上是一样的。应该是一个很基础的问题把我卡在这里了。

neolee commented 4 years ago

我这种写法是把判断是不是素数的逻辑写道迭代器里,本质上是一样的

我知道你是想偷懒把 is_prime() 的功能写在 __next__(),但是,你这写的“本质是一样”吗?

你的注释里写“执行这个方法,判断是否是素数,如果不是 break 跳出 for 循环”,那如果是素数呢?

如果 self.base 是素数,for 循环会跑完结束;如果 self.base 不是素数,for 循环会 break 结束,总之都会结束循环,然后执行后面的代码——所以是不是素数,对你的代码来说有啥区别?结果不是都一样吗?

所以我课上推荐大家先写清楚自己的逻辑,而不是写完代码再补点注释,因为你有了代码之后思路就被你的代码限制了,就不清晰了,这叫思维惯性。你们现在对代码的掌控还很不稳固,所以一开始先要明确逻辑,用逻辑框住代码。

把一些确定的独立功能写成函数,也有这个目标在里面,防止复杂的逻辑把自己弄晕——就像你现在这样就是被稍微复杂的逻辑搞晕了,拆开一个 is_prime() 函数就比较不容易出这种问题。学会走之前别跑。