user
user

Reputation: 2884

Implementation of iterator protocol without __iter__ method in class

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 ?

Upvotes: 0

Views: 38

Answers (1)

chepner
chepner

Reputation: 531878

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.

Upvotes: 1

Related Questions