def __iter__(self):
return self
Just wanted to know what does the above code do in general, why is it required.
I went through many code tutorial and blocks, was getting mutiple answers without any proper specification, just a brief explanation would be great.
The __iter__() function returns an iterator for the given object (array, set, tuple, etc. or custom objects). It creates an object that can be accessed one element at a time using __next__() function, which generally comes in handy when dealing with loops.
The __iter__() method acts similar, you can do operations (initializing etc.), but must always return the iterator object itself. The __next__() method also allows you to do operations, and must return the next item in the sequence.
return self would return the object that the method was called from.
The __iter__() method returns the iterator object itself. If required, some initialization can be performed. The __next__() method must return the next item in the sequence. On reaching the end, and in subsequent calls, it must raise StopIteration .
EDIT: for 2.7 instead of 3
Here is my understanding
In below example code, we can say that class Testing is an iterable object because we implemented it with __iter__
. Method __iter__
returns an iterator. The iterator uses the next method to determine the next value on the iteration. If I were to remove the next
method from the class below, the code would fail.
iterable = an object that can be iterated over...implemented with __iter__
iterator = object that defines how to iterate...literally, what is the next value. This is implemented with __next__
So the piece of code you questioned actually takes the class object (self is the argument) and returns an iterator, which makes the class object iterable. So in the example below we can actually iterate over the class object myObj.
class Testing:
def __init__(self,a,b):
self.a = a
self.b = b
def __iter__ (self):
return self
def next(self):
if self.a <= self.b:
self.a += 1
return self.a-1
else:
raise StopIteration
myObj = Testing(1,5)
for i in myObj:
print i
It's a bit confusing. In short, defining __iter__ to return self is essentially turning an iterator object into an iterable quickly so that you can use it in a for loop.
Recall that an iterator is an object with a next method for the purpose of returning the next item in the process of performing a iteration. After the next method is called, the state of the iterator changes.
Recall that an iterable is an object with an __iter__ method, whose purpose is to return a fresh iterator to perform a iteration.
To separate the concepts, let's take the example of the iterator OneToFourIterator and the iterable OneToFourIterable
class OneToFourIterator:
def __init__(self):
self.state = 0
def next(self):
self.state += 1
if self.state > 4:
raise StopIteration
return self.state
class OneToFourIterable:
def __init__(self):
pass
def __iter__(self):
return OneToFourIterator()
To perform a iteration using a for loop, you have to give it an iterable like this,
for i in OneToFourIterable():
print i
If you use an iterator in a for loop, it will give an error. To use an iterator for iteration, you would do something like this
iterator = OneToFourIterator()
while True:
try:
current = iterator.next()
print current
except StopIteration:
break
Finally, I think the answer to why people define __iter__ to return self, is that instead of writing 2 classes like the above, you can quickly turn an iterator into an iterable so that you can use it in a for loop:
class OneToFourIteratorAndIterable:
def __init__(self):
self.state = 0
def next(self):
self.state += 1
if self.state > 4:
raise StopIteration
return self.state
pass
def __iter__(self):
return self
for i in OneToFourIteratorAndIterable():
print i
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With