pete the dude pete the dude - 3 years ago 299
Python Question

Python class and __iter__

What are the benefits of using the

__iter__
function in a Python class?

In the code below I am just setting up two simple classes. The first class takes in a list as an argument, and I am able to loop over this list without using the
__iter__
function. The second bit of code uses the
__iter__
function to loop over a list.

What is the benefit of using
__iter__
when there are already ways of looping over stuff in a class?

EG 1: no __iter__


class test_class:
def __init__(self, list):
self.container_list = list

def print (self):
a = self.container_list
return a

test_list = test_class([1,2,3,4,5,6,7])

x = test_class.print(test_list)

for i in x:
print (i)



EG 2: yes __iter__

class list_using_iter:
def __init__(self):
self.list = [1,2,3,4]
self.index = -1

def __iter__(self):
return self

def __next__(self):
self.index += 1
if self.index == len(self.list):
raise StopIteration
return self.list [self.index]

r = list_using_iter()
itr = iter(r)

print(next(itr))
print(next(itr))
print(next(itr))
print(next(itr))

print(next(itr)) # Raises the exception!

Answer Source

Your first example is not iterable, but contains an attribute that is. Your second example is iterable, but you iterate simply by "following" another iterable. Here's an example of a iterable that does more work itself:

import itertools

class Fibs:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __iter__(self):
        a = self.a
        b = self.b
        while True:
            yield a
            a, b = b, a + b

real_fibs = Fibs(0,1)

for i in itertools.islice(real_fibs, 10):
    print(i)

Fibs.__iter__ isn't simply regurgitating values obtained from some other value's __iter__ method; it is computing and yielding new values on demand.


Actually, the preceding is an example of a class that knows how to create its own iterator, rather than having each object be iterable. Here's a version that defines next itself.

class Fibs:
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __iter__(self):
        return self

    def __next__(self):
        rv = self.a
        self.a, self.b = self.b, self.a + self.b
        return rv
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download