0

I have tried with this code to implement iterator protocol, and every thing works fine.
Ideally it shouldn't as I have not implemeted iter().

class PowerofTwo():
    def __init__(self,maxi):
        self.max = maxi
        self.num = 0     

    def __next__(self):
        if self.num < self.max:
            result = 2 ** self.num
            self.num += 1
            return result
        else:
            raise StopIteration


myObj = PowerofTwo(5)

print(type(myObj)) #print <class '__main__.PowerofTwo'>
print(next(myObj)) #print 1

Even if assume that __iter__() method is available by default like __init__().
But not able to understand how can I directly call next() and skip calling iter(obj) at first place.
If I try same thing with list or other builtin iterator, I gets error that object is not an iterator.

Am I missing something basic here ?

5
  • __next__ is exactly the method that the next() function tries to call, and your class has a __next__ method. Why do you expect it not to work? Commented Apr 24, 2020 at 15:59
  • 1
    PowerofTwo is an iterator, but it is not iterable. An iterable is something you can pass to iter; an iterator is the thing that iter returns and can be passed to next. Commented Apr 24, 2020 at 16:06
  • Some things, like the objects returned by open, are both iterable and iterators. Others, like list, are iterable, but not iterators. iter([1,2,3]) returns not the list, but a value of type list_iterator. Commented Apr 24, 2020 at 16:07
  • @chepner What modifications are required to make PowerofTwo an iterable ? Commented Apr 24, 2020 at 16:10
  • You need to define __iter__, but it doesn't have to do anything other than return self. Commented Apr 24, 2020 at 16:10

1 Answer 1

1

Currently, PowerofTwo is an iterator, but it is not an iterable. To make it iterable, you need to define __iter__ to return an object that has a __next__ method. In this case, the instance of PowerofTwo itself will do.

class PowerofTwo:
    def __init__(self,maxi):
        self.max = maxi
        self.num = 0     

    def __iter__(self):
        return self

    def __next__(self):
        if self.num < self.max:
            result = 2 ** self.num
            self.num += 1
            return result
        else:
            raise StopIteration


for x in PowerofTwo(5):
    print(x)

outputs

 1
 2
 4
 8
 16

It is considered good practice to always define

def __iter__(self):
    return self

in a class that defines __next__.

list is an example of a class whose __iter__ method returns an instance of another class, namely list_iterator.

Sign up to request clarification or add additional context in comments.

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.