繁体   English   中英

关于迭代我做错了什么

[英]What am I doing wrong regarding iteration

我想打印出呼叫中给定的所有奇数: 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

您的if分支不会返回任何内容 ,因此您始终raise StopIteration在此时达到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不知道, 您的代码需要产生那个

您的特定问题是,第一个偶数将落入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)

另外,您还可以通过提供start值和step值使它更加通用:

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()功能,所以我只用它。 除非您的目的是自我教育,否则请自娱自乐。

除非您需要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))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM