# Convert map object to numpy array in python 3

10k Views

In Python 2 I could do the following:

``````import numpy as np
f = lambda x: x**2
seq = map(f, xrange(5))
seq = np.array(seq)
print seq
# prints: [ 0  1  4  9 16]
``````

In Python 3 it does not work anymore:

``````import numpy as np
f = lambda x: x**2
seq = map(f, range(5))
seq = np.array(seq)
print(seq)
# prints: <map object at 0x10341e310>
``````

How do I get the old behaviour (converting the `map` results to `numpy` array)?

Edit: As @jonrsharpe pointed out in his answer this could be fixed if I converted `seq` to a list first:

``````seq = np.array(list(seq))
``````

but I would prefer to avoid the extra call to `list`. • I was actually aware about the `list` solution, but I was asking about a direct one.
• Without converting to `list` fist. I forgot to mention it.

One more alternative, other than the valid solutions @jonrsharpe already pointed out is to use `np.fromiter`:

``````>>> import numpy as np
>>> f = lambda x: x**2
>>> seq = map(f, range(5))
>>> np.fromiter(seq, dtype=np.int)
array([ 0,  1,  4,  9, 16])
``````
• 2
• `fromiter`'s example is essentially this: `np.fromiter((x*x for x in range(5)),int)`.

Although you refer to it as `seq`, the `map` object in Python 3 is not a sequence (it's an iterator, see what's new in Python 3). `numpy.array` needs a sequence so the `len` can be determined and the appropriate amount of memory reserved; it won't consume an iterator. For example, the `range` object, which does support most sequence operations, can be passed directly;

``````seq = np.array(range(5))
print(seq)
# prints: [0 1 2 3 4]
``````

To restore the previous behaviour, as you're aware, you can explicitly convert the `map` object back to a sequence (e.g. list or tuple):

``````seq = np.array(list(seq))  # should probably change the name!
``````

However, as the documentation puts it:

a quick fix is to wrap `map()` in `list()`, e.g. `list(map(...))`, but a better fix is often to use a list comprehension (especially when the original code uses `lambda`)

So another option would be:

``````seq = [f(x) for x in range(5)]
``````

or just:

``````seq = [x**2 for x in range(5)]
``````

Alternatively, actually use `numpy` from the start:

``````import numpy as np
arr = np.arange(5)
arr **= 2
print(arr)
# prints [ 0  1  4  9 16] in 2.x and 3.x
``````
• @btel no, `np.array` won't consume the iterator. You need the full list up-front so the appropriate memory can be reserved.