Why do I need iter when there is next?
I'm learning python and I have a question about iterators.
In order to iterate over an object, it must have a __iter__
method that returns an iterator object.
The iterator object must have a method __next__
that will return the next element from the object that we iterate on, or throw an error StopIteration
.
I've only seen code like this where __iter__
returns self
.
For example
class RandomIterator:
def __iter__(self):
return self
def __init__(self, k):
self.k = k
self.i = 0
def __next__(self):
if self.i < self.k:
self.i += 1
return random()
else:
raise StopIteration
So I have a question, what is the meaning of the __iter__
method?
3 answers
As you learned in the Python Classes and Objects tutorial, all classes have a function called
__init__()
that allows you to do initialization when creating an object.The
__iter__()
method works similarly, you can perform operations (initialization, etc.), but you must always return the iterator object itself.
Now, when it comes to creating your own In Python, it's time to talk about protocols. Protocols are a bit like interfaces in other languages in that they provide a set of methods that you have to implement. However, in Python, the protocols are absolutely non-binding and do not necessarily require the implementation of any declaration. They're probably more like guidelines.
Why are we talking about protocols? Because the implementation of arbitrary container types in Python entails it is a use of some of them. First, the protocol for defining immutable containers: to create an immutable container, you only need to define
__len__
and__getitem__
(more on them later). The mutable container protocol requires the same as the immutable container, plus__setitem__
and__delitem__
. Finally, if you want your objects to be iterable, you must define__iter__
, which returns the iterator. This iterator must conform to the protocol an iterator that requires the__iter__
(returns itself) and next methods.
__iter__(self)
Must return an iterator for the container. Iterators are returned in a variety of situations, mainly for the built-in functioniter()
and in the case of iterating through the container elements with the expressionfor x in container:
. Iterators are objects in themselves, and they too must define a method__iter__
that returnsself
.
UPDATE (I returned an example with the code, because I was asked in the comments): Here in for example, the 1st link has one of the options for why. When you need to count the number of elemets processed or other related operations. This is useful for reducing code duplication (see Python principles) iter() in Python
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
return x
And below is my example of using __iter__
class Fibbonachi:
def __iter__(self):
self.cur_val = 0
self.next_val = 1
return self
def __next__(self):
tmp = self.next_val
self.next_val += self.cur_val
self.cur_val = tmp
return tmp
for i in Fibbonachi():
print(i)
if i > 100: break
# Результат: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144 в колонку
In general, this approach (using only __iter__
) is much simpler in my opinion, so the question should rather be the opposite, why do you need __next__
:)
class RandomIterator:
def __iter__(self):
while self.i < self.k:
self.i += 1
yield random()
def __init__(self, k):
self.k = k
self.i = 0
So I have a question, what is the meaning of the iter method?
__iter__
this is just a good design that separates the iterator from the object itself or container that you iterate on, you can do without it for your example.
For any questions, please refer to the official literature and primary sources: https://docs.python.org/3/tutorial/classes.html#iterators