Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 672
Curious2learn Avatar asked Dec 11 '22 19:12

Curious2learn


2 Answers

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)
like image 105
ecatmur Avatar answered May 03 '23 20:05

ecatmur


You are using map() incorrectly. It should not be used for the side effects of the function call, but to transform an iterable.

You can use list(itertools.imap(f, range(3))) to get the behavior you want, but I would argue that you should change your entire approach to use a normal for loop:

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

This makes it clear that the return values from the f() calls are not being used.

like image 24
Andrew Clark Avatar answered May 03 '23 19:05

Andrew Clark