Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python list __iter__ method called on every loop?

I am trying to make a class which inherits from a python list. I want the elements of the list to be initialized/finalized with every loop of the list. I thought this could be done by overriding the __iter__ method of the python list but I can't seem to get it to work. The __iter__ method appears to called only once ? (see below)

class MyList(list):
    def __iter__(self):
        print 'do something'
        return list.__iter__(self)

my_list = MyList(range(10))
print my_list

for item in my_list:
    print item

Output

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
do something
0
1
2
3
4
5
6
7
8
9

Any idea how I can achieve what I want to do?

like image 675
scruffyDog Avatar asked Mar 30 '11 01:03

scruffyDog


3 Answers

You can simply return a generator expression from __iter__()

class MyList(list):
    def __iter__(self):
        return (self.do_something(x) for x in list.__iter__(self))

    def do_something(self, x):
        print 'do something', x
        return x

my_list = MyList(range(10))
print my_list

for item in my_list:
    print item

ncoghlan suggests using a generator in place of the generator expression which makes for easier debugging

class MyList(list):

    def __iter__(self):
        for x in list.__iter__(self):
            yield self.do_something(x)

    def do_something(self, x):
        print 'do something', x
        return x

my_list = MyList(range(10))
print my_list

for item in my_list:
    print item

alternatively you could use imap here

from itertools import imap

class MyList(list):
    def __iter__(self):
        return imap(self.do_something, list.__iter__(self))

    def do_something(self, x):
        print 'do something', x
        return x


my_list = MyList(range(10))
print my_list

for item in my_list:
    print item
like image 155
John La Rooy Avatar answered Oct 20 '22 23:10

John La Rooy


__iter__ returns an iterator object. If you need to do something in every iteration, you have to implement your own (it has to implement two methods described in the linked docs).

like image 26
Cat Plus Plus Avatar answered Oct 21 '22 00:10

Cat Plus Plus


The python class __iter__() method actually returns an iterator object. See the following for reference: http://docs.python.org/library/stdtypes.html#iterator-types

On the iterator object the next() method will be called on each step of the loop. You could write a custom iterator which would be returned by your custom list.

like image 37
William Avatar answered Oct 20 '22 22:10

William