关于迭代,我做错了什么

时间:2015-09-23 07:36:27

标签: python python-3.x iterator

我想打印出来电中给出的所有奇数: o = Odds(10),输出应该是1, 3, 5, 7, 9,但我在评论区域做错了,它应该相对简单但我无法看到它。

class Odds:
    def __init__(self, arg):
        self.num = arg

    def __iter__(self):
        return OddsIterator(self.num)

class OddsIterator:
    def __init__(self, arg):
        self.high = arg
        self.low = 1

    def __next__(self):
        if self.low <= self.high:
            if (self.low % 2) == 0: #somethings wrong around here
                self.low += 1 
            else:
                self.low += 1
                return self.low - 1
        raise StopIteration

3 个答案:

答案 0 :(得分:2)

您的if分支机构无法返回任何内容,因此您始终可以到达raise StopIteration。说low为2,high为10:

if self.low <= self.high:  # true, 2 <= 10
    if (self.low % 2) == 0:  # true, 2 is even
        self.low += 1 
    # else branch is skipped, so we come to the next line
raise StopIteration  # iterator ends

您需要在__next__中创建更大的步骤,因为该方法始终会返回一些内容。总是在序列中返回下一个数字,而不是在数字为偶数时不返回,所以每次将self.low增加2,并且第一次确保以奇数开头:

def __next__(self):
    if self.low > self.high:
        raise StopIteration
    if self.low % 2 == 0:
        self.low += 1  # ensure we get an odd number first
    retval = self.low
    self.low += 2
    return retval

我在这里反转了对StopIteration条件的测试,以便更清楚地知道当仍然有一个值从迭代中返回时函数总是返回一些东西。

只是为了重新迭代,__next__ 总是会返回一些东西,你不能期望它不会返回某些内容,所以它会在 至少返回None。迭代器不计算。 Python没有去让我们询问结果是1,然后是2,然后是3 。 Python只是询问奇数序列中的下一个值是。在1之后,来了3,但是Python并不知道,你的代码需要产生

答案 1 :(得分:2)

您的具体问题是,第一个偶数会落到StopIteration行,使您的序列变短:{ 1 }

在我看来,生成所有奇数应该更容易。从-1开始,然后在每次通话时开始:

  • 添加两个。
  • 如果太高,请停止。
  • 否则返回当前值。

可以通过以下方式实现:

class Odds:
    def __init__(self, arg):
        self.num = arg

    def __iter__(self):
        return OddsIterator(self.num)

class OddsIterator:
    def __init__(self, arg):
        self.high = arg
        self.curr = -1

    def __next__(self):
        self.curr += 2
        if self.curr > self.high:
            raise StopIteration
        return self.curr

o = Odds(10)
for i in o:
    print (i)

话虽如此,我不确定我是否会像你一样实施它。当你可以将它们组合成一个单独的类时,似乎没有必要有两个单独的类:

class Odds:
    def __init__(self, end):
        self.curr = -1
        self.lim = end

    def __next__(self):
        self.curr += 2
        if self.curr > self.lim:
            raise StopIteration
        return self.curr

    def __iter__(self):
        return self

o = Odds(10)
for i in o:
    print (i)

此外,通过提供startstep值,您可以更加通用:

class XFor:
    def __init__(self, start, end, step):
        self.curr = start - step
        self.lim = end
        self.step = step

    def __next__(self):
        self.curr += self.step
        if self.curr > self.lim:
            raise StopIteration
        return self.curr

    def __iter__(self):
        return self

o = XFor(1,10,2)
for i in o:
    print (i)

虽然它正在危险地侵占range()所做的事情,所以我只是使用它。除非你的意图是自我教育,否则在这种情况下玩得很开心。

答案 2 :(得分:0)

如何使用简单的生成器来实现此目的,除非您将Odds类用于其他目的 -

def odds(num):
    for i in range(1, num + 1):
        if i % 2 != 0:
            yield i

print(list(odds(11)))

如果您确实想要出于特定原因使用课程Odds -

class Odds:

    def __init__(self, num):
        self.high = num

    def __iter__(self):
        return odds(self.high)

print(list(Odds(10))