开发者

python list __iter__ method called on every loop?

I am开发者_如何学Go 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?


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


__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).


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.


I want the elements of the list to be initialized/finalized with every loop of the list

A list has no direct control over this. Several loops can access a list in parallel (e.g. in nested loops). Each loop is controlled by an iterator, and __iter__() should return iterators, every time it's called. You can't return the same iterator instance all the time, because said parallel loops will then interfere with each other.

But inside an iterator you're free to instantiate items as you need. Finalizing them from inside the iterator is hardly wise, because once you returned an item, you lost control over it. If you finalize it at a later moment, outer code that still relies on the item may fail. If you need to finalize your items, make it a responsibility of items' consumer.


I don't understand exactly what you are trying to do, but what you've already been told is true. next() is the method called in every iteration.

class MyList(list):
    def next(self):
        print "Do something"
        return list.next(self)

(I didn't tested it)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜