[英]What am I doing wrong regarding iteration
I want to print out all the odd numbers given in the call: o = Odds(10)
, the output should be 1, 3, 5, 7, 9
but I'm doing something wrong in the commented area, it should be relatively simple but I can't see it. 我想打印出呼叫中给定的所有奇数:
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
Your if
branch doesn't return anything , so you always reach raise StopIteration
at that point. 您的
if
分支不会返回任何内容 ,因此您始终raise StopIteration
在此时达到raise StopIteration
。 Say low
is 2 and high
is 10: 假设
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
You need to create larger steps in __next__
, because that method always returns something. 您需要在
__next__
创建更大的步骤,因为该方法总是返回某些内容。 Instead of not returning when a number is even, you need to return the next number in the sequence, always, so increment self.low
by 2 each time, and the first time make sure you start with an odd number: 您需要始终返回序列中的下一个数字,而不是在偶数时不返回,因此每次将
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
I inverted testing for the StopIteration
condition here to make it clearer that the function always returns something when there is still a value to return from the iterable. 我在这里反转了
StopIteration
条件的测试,以更清楚地表明,当仍有可迭代对象返回的值时,该函数总是返回某些内容。
Just to re-iterate, __next__
always returns something, you can't expect it to not return something, so it'll at the very least return None
. 仅重申一下,
__next__
总是返回某些内容,您不能指望它不返回任何内容,因此它至少会返回None
。 The iterator is not counting . 迭代器没有计数 。 Python doesn't go lets ask what the result is for 1, then for 2, then for 3 .
Python不走了, 让我们问一下1,2,3的结果是什么 。 Python simply asks what the next value in the sequence of odd numbers is .
Python只是问奇数序列中的下一个值是什么 。 After 1, comes 3, but Python doesn't know that, your code needs to produce that .
1之后是3,但是Python不知道, 您的代码需要产生那个 。
Your specific problem is that the first even number will fall through to the StopIteration
line, rendering your sequence rather short: { 1 }
. 您的特定问题是,第一个偶数将落入
StopIteration
行,从而使序列变得很短: { 1 }
。
It seems to me that generating all the odd numbers should be substantially easier. 在我看来,生成所有奇数应该实质上更容易。 Start with
-1
then, on every call: 从
-1
开始,然后在每个通话中:
That can be achieved with: 可以通过以下方法实现:
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)
Having said that, I'm not sure I'd implement it the same way you did. 话虽如此,我不确定我会采用与您相同的方式来实现它。 It seems unnecessary to have two separate classes when you can combine them into a single one:
当您可以将它们组合成一个类时,似乎没有必要拥有两个单独的类:
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)
In addition, you can make it far more general by providing start
and step
values as well: 另外,您还可以通过提供
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)
Although it's then encroaching dangerously on what range()
does so I'd just use that. 尽管它然后危险地侵犯了
range()
功能,所以我只用它。 Unless your intent is self-education, in which case have fun. 除非您的目的是自我教育,否则请自娱自乐。
How about using a simple generator for this purpose, unless you need the Odds class for other purposes - 除非您需要Odds类用于其他目的,否则如何为此目的使用简单的生成器-
def odds(num):
for i in range(1, num + 1):
if i % 2 != 0:
yield i
print(list(odds(11)))
If you do want to use class Odds
for specific reason - 如果您确实出于特定原因想要使用类别
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.