Why Does Map Return a Map Object Instead of a List in Python 3

Why does map return a map object instead of a list in Python 3?

I think the reason why map still exists at all when generator expressions also exist, is that it can take multiple iterator arguments that are all looped over and passed into the function:

>>> list(map(min, [1,2,3,4], [0,10,0,10]))
[0,2,0,4]

That's slightly easier than using zip:

>>> list(min(x, y) for x, y in zip([1,2,3,4], [0,10,0,10]))

Otherwise, it simply doesn't add anything over generator expressions.

Getting a map() to return a list in Python 3.x

Do this:

list(map(chr,[66,53,0,94]))

In Python 3+, many processes that iterate over iterables return iterators themselves. In most cases, this ends up saving memory, and should make things go faster.

If all you're going to do is iterate over this list eventually, there's no need to even convert it to a list, because you can still iterate over the map object like so:

# Prints "ABCD"
for ch in map(chr,[65,66,67,68]):
print(ch)

Python 3 map is returning a list of NoneType objects instead of the type I modified?

This is because, your incr_number doesn't return anything. Change it to:

def incr_number(self, incr=0):
self.number += incr
return self

Understanding the map function

map isn't particularly pythonic. I would recommend using list comprehensions instead:

map(f, iterable)

is basically equivalent to:

[f(x) for x in iterable]

map on its own can't do a Cartesian product, because the length of its output list is always the same as its input list. You can trivially do a Cartesian product with a list comprehension though:

[(a, b) for a in iterable_a for b in iterable_b]

The syntax is a little confusing -- that's basically equivalent to:

result = []
for a in iterable_a:
for b in iterable_b:
result.append((a, b))

Map object empties itself after converting to list

In Python 3.x, map doesn't return a list object, instead it returns an iterator.

Return an iterator that applies function to every item of iterable, yielding the results.

Basically, it doesn't process all the elements of the iterable passed immediately. It just processes one at a time, whenever asked for it.

In your case, all the elements from the range objects are processed one by one and when all of them are processed, the iterator object returned by map is exhausted (there is nothing else left to be processed). That is why you are getting empty list, when you do list(squares) the second time.

For example,

>>> squares = map(lambda x: x**2, range(10))
>>> next(squares)
0
>>> next(squares)
1
>>> next(squares)
4
>>> next(squares)
9

here, we have just processed the first four items, on demand. The values were not calculated before-hand, but the lambda function is called with the next value from the iterator passed to squares (range(10)), when you actually did next(squares) and the value is returned.

>>> list(squares)
[16, 25, 36, 49, 64, 81]

now, only the rest of the items in the iterator are processed. If you try to get the next item,

>>> next(squares)
Traceback (most recent call last):
File "<input>", line 1, in <module>
StopIteration

since the squares is exhausted, StopIteration is raised and that is why list(squares) is not getting any elements to process and returns an empty list.



Related Topics



Leave a reply



Submit