Yaron Scherf
Yaron Scherf

Reputation: 105

Iter built in function with classes

class Kids():
    def __init__(self, list_of_kids):
        self.kids = list_of_kids

    def __next__(self):
        return 'kawabanga'
    def __iter__(self):
        return self

kid = Kids([1,2,3])
kids_iter = iter(kid)
print(kid)
print(kids_iter)
print(iter([1,2,3]))

I've built the code above as an example. I receive the following output:

<__main__.Kids object at 0x102977b38>
<__main__.Kids object at 0x102977b38>
<list_iterator object at 0x102977be0>

As far as I understand: iter() should return an iterator object, but as you can see when I enter the function iter() the object Kids it returns a Kids object instead of an iterator object.

Can you please explain me why it doesn't return an iterator object when I call iter() on the object Kids?

Upvotes: 0

Views: 143

Answers (2)

instant
instant

Reputation: 696

This happens because you are overwriting iter() behaviour when setting __iter__ on the class. As you can see, you return self, so you basically redefined what iter(Kids) does.

The correct way to implement this is to yield, instead of return in __iter__. This of course only makes sense if you plan on combining it with something like a for loop, so that you iterate over multiple objects. Otherwise __iter__ and __next__ will only ever give you a single object instance.

Upvotes: 2

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160437

Because you return self from Kids.__iter__ and not a special iterator object as list objects do (list_iterator).

Your class is itself the iterator since it defines __iter__ and __next__.

If, instead, you want to handle the iteration at a separate object for the Kids class (and there's plenty of reasons to want to do that), create a Kids_Iterator object that defines __iter__ and __next__ and make Kids.__iter__ return a new instance of the Kids_Iterator class.

Upvotes: 3

Related Questions