Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the use of returning self in the __iter__ method?

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.

like image 686
Smple_V Avatar asked Feb 26 '16 17:02

Smple_V


People also ask

What does __ ITER __ return?

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.

What kind of object should the __ Iter__ method return?

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.

What does returning self do Python?

return self would return the object that the method was called from.

Which method returns the iterator object itself?

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 .


2 Answers

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
like image 59
bvmcode Avatar answered Oct 12 '22 23:10

bvmcode


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
like image 28
user2191332 Avatar answered Oct 13 '22 01:10

user2191332