(In Python 3.1) (Somewhat related to another question I asked, but this question is about iterators being exhausted.)
# trying to see the ratio of the max and min element in a container c
filtered = filter(lambda x : x is not None and x != 0, c)
ratio = max(filtered) / min(filtered)
It took me half hour to realize what the problem is (the iterator returned by filter is exhausted by the time it gets to the second function call). How do I rewrite it in the most Pythonic / canonical way?
Also, what can I do to avoid bugs of this sort, besides getting more experience? (Frankly, I don't like this language feature, since these types of bugs are easy to make and hard to catch.)
The
itertools.tee
function can help here:The entity
filtered
is essentially an object with state. Of course, now it's obivous that runningmax
ormin
on it will change that state. In order to stop tripping over that, I like to make it absolutely clear (to myself, really) that I am constructing something rather than just transforming something:Adding an extra step can really help:
Whether you put
filtered(...)
inside some function (maybe it's not really needed for anything else) or define it as a module-level function is up to you, but in this case I'd suggest that iffiltered
(the iterator) was only needed in the function, leave it there until you need it elsewhere.The other thing you can do is to construct a
list
from it, which will evaluate the iterator:(Of course, you can just say
filtered = list(filter(...))
.)Actually your code raises an exception that would prevent this problem! So I guess the problem was that you masked the exception?
Anyways, you can also write a new function to give you the min and max at the same time:
you can convert an iterator to a tuple simply by calling
tuple(iterator)
however I'd rewrite that filter as a list comprehension, which would look something like this