2

I have just learned about iterators in Python however I am having a hard time implementing them.

I am trying to write a class to so that this loop works:

  odds = OddNumbers(13)
  for i in odds:
      print(i) 

I want to write an iter() function and next() function to do this.

So far I have:

class OddNumbers:

    def __init__(self, number):
        self.number = number

    def __iter__(self):
        return self

    def __next__(self):
        current = self.number
        if self.number%2 == 0:
            return current
        else:
            raise StopIteration

But at the moment this is returning nothing. I expect the output to be

1
3
5
7
9
11
13

Help?

7
  • What are you trying to do? You have only one element. Why do you need this class to be an iterable? Commented May 14, 2015 at 5:55
  • 1
    What numbers should the example code print? Commented May 14, 2015 at 5:56
  • If you start with an odd number, then __next__ will only raise StopIteration. If you start with an even number, it will only return that number. Did you mean for __next__ to decrement self.number each time? Commented May 14, 2015 at 5:58
  • @user2357112 Apologies for not putting that in my original post, I forgot! I have edited it in now though. Commented May 14, 2015 at 5:58
  • In your case, __next__ will raise an exception in the first loop, so the iterator stopped, that's why there is nothing print. Commented May 14, 2015 at 5:59

4 Answers 4

3

Your object needs to keep track of its state and update it when __next__ is called.

class OddNumbers(object):
    def __init__(self, number):
        self.current = ...
        self.number = number

    def __iter__(self):
        return self

    def __next__(self):
        # Update self.current
        # If the limit has been reached, raise StopIteration
        # Otherwise, return something
Sign up to request clarification or add additional context in comments.

Comments

1

You need another variable to track the current number:

def __init__(self, number):
    self.number = number
    self.current = 1

Then you need to compare it with the ending number, and maybe increment it:

def __next__(self):
    if self.current > self.number:
        raise StopIteration
    current = self.current
    self.current += 2
    return current

4 Comments

Thank you very much! This solved my issue! At one stage I did have another variable to track the number of iterations, except I didn't initialize it with the init method, I only introduced it in the next. Thank you again!
You shouldn't tell the OP the whole answer, this doesn't teach them anything.
@augurar, the OP showed effort and posted real code so an answer is the right response. The comment showed he learned from this.
@BrentWashburne You just told him the answer. So he learned what the correct answer was. Good job, I guess.
0

There is probably a much cleaner way of doing this, but here is a quick stab:

class OddNumbers:

    def __init__(self, number):
        self.number = number

    def __iter__(self):
        self.current = self.number
        return self

    def __next__(self):
        if self.current > 0:
            if self.current % 2 == 0:
                self.current -= 1
            self.current -= 1
            return self.current + 1
        raise StopIteration

Comments

0

This will give you an iterator-like object which provides even or odd numbers. However, it won't satisfy your for loop semantics as it is not a true iterator.

class NumberIterator(object):
    """Returns simple even/odd number iterators."""
    def __init__(self, current):
        self.current = current
    def next(self):
        self.current += 2
        return self.current
    @classmethod
    def getOddIterator(cls):
        return cls(-1) # start at 1
    @classmethod
    def getEvenIterator(cls):
        return cls(0) # start at 2


    odd_numbers = NumberIterator.getOddIterator()
    even_numbers = NumberIterator.getEvenIterator()

    odd_numbers.next() # Returns 1
    odd_numbers.next() # Returns 3

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.