Reputation: 21
What exactly is the role of iter? Consider the following code block:
class Reverse:
def __init__(self,data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def next(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
omitting iter(self) and rewritting:
class Reverse2:
def __init__(self,data):
self.data = data
self.index = len(data)
def next(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
Then:
x = [1,2,3]
y = Reverse(x)
z = Reverse2(x)
y.next()
>>> 3
y.next()
>>> 2
y.next()
>>> 1
z.next()
>>> 3
z.next()
>>> 2
z.next()
>>> 1
The classes behave the same way regardless of whether I include iter() or not, so why should i include it in the first place? I'm sorry if my question isn't clear--I simply don't know how to state it in a more clear way...
Upvotes: 0
Views: 96
Reputation: 42758
The __iter__
method is always called, when an iterator is needed, e.g. by explicitly calling iter
or in for
-loops or when creating lists list(xy)
.
So you cannot use your second class Reverse2
in all these contexts.
>>> list(Reverse("abc"))
['c', 'b', 'a']
>>> list(Reverse2("abc"))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: iteration over non-sequence
To answer the question in the comment: the __iter__
-method must return any iterator or instance with a __next__
-method. Only if your class is a iterator by itself, it should return self
. An example of returning a generator as iterator:
class Reverse3:
def __init__(self,data):
self.data = data
def __iter__(self):
# returns an generator as iterator
for idx in range(len(self.data)-1, -1, -1):
yield self.data[idx]
Upvotes: 1
Reputation: 6288
The __iter__ return the iterator object which allows to convert the object to a container which can be iterated via for .. in ..
.
The iterator object is any object which define __next__ method which returns the next item if exists or raise StopIteration
otherwise.
While __iter__ can return any such iterator object, It can return itself if it implement __next__ method.
For example:
class Reverse:
def __init__(self,data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
Now you can use in for loops:
for xx in Reverse(x):
print xx
Upvotes: 0