Search code examples
pythondictionarypython-itertools

python map vs itertools.map: Make the iterator version behave like the former


Consider the following example code. The example is given just to highlight the different functionality between map and itertools.imap. What I really want to do cannot be done with a list comprehension because in my real problem I am not creating a list but filling a larger numpy array with small arrays. So in response to the code below, please do not suggest: [f(x) for x in range(3)]

Example:

g = []

def f(x):
    g.append(x)

The results I get with map and itertools.map:

map(f, range(3)) # Results in g = [0,1,2]

itertools.imap(f, range(3)) # Does not change g

I want the g to change as done by the map function. However, I have heard that map will (or does) behave like itertools.imap in Python 3. Even though I am using Python 2.7 I want to learn the correct way of using an iterator version of the map. How do I use itertools.imap to achieve the same outcome as I get with map?

I can do:

b = itertools.imap(f, range(3))
list(b) # This gives g = [0,1,2] if starting with an empty g.

Is this the correct way, or is there a better way?

Thanks in advance.


Solution

  • itertools functions return generators; they only operate when iterated over. So itertools.imap(f, range(3)) won't actually do anything until you run it to completion e.g. with list.

    Per http://docs.python.org/2/library/itertools.html#recipes, the most efficient way to consume an iterator is with a zero-length deque:

    collections.deque(itertools.imap(f, range(3)), maxlen=0)
    

    However, if you're calling a function for its side effects you should be using an imperative as opposed to functional syntax:

    for i in range(3):
        f(i)