Reputation: 19
I came across this scraping problem which itself is irrelevant but want to know if it is possible to perform map() from a list comprehension meaning the iterable be a list comprehension?
The following returns the empty list where I expected [0, 2, 4, 6, 8]
:
def foo() -> list[int]:
result: list = []
map(result.append, [x for x in range(10) if x % 2 == 0])
print(result)
I guess the question is could the iterable for map function itself be a list comprehension or not? This specific example isn't itself important.
Upvotes: -3
Views: 66
Reputation: 33
Your code doesn't work because the map
function returns an iterator so as you didn't iterate over the object returned by map
, the result.append
function is never called.
The "just working" version of your code would be something like:
def foo() -> list[int]: # Note that the type hint here is incorrect as you don't return anything
result: list = []
tuple(map(result.append, [x for x in range(10) if x % 2 == 0]))
print(result)
But this is very unoptimized, the version I would write would use directly the list comprehension:
def foo():
print([x for x in range(10) if x % 2 == 0])
Otherwise you could use a filter:
def foo():
print(list(filter(lambda x: x % 2 == 0, range(10))))
For more information, please read this article: https://realpython.com/python-map-function/
Upvotes: 3
Reputation: 159752
The second argument to map
can be any iterable, including a list comprehension. That's fine.
The actual problem is that map
itself returns an iterable, that doesn't do anything until it's consumed. You could put this itself in something like a for
loop, like
result: list[int] = []
iter = map(result.append, [x for x in range(10) if x % 2 == 0])
for x in iter:
print(f"This is the result of result.append, which is None: {x}")
print(result)
Note that the list comprehension itself is just syntactic sugar around map
and filter
, but putting it in list syntax forces the iterator to be resolved to a list, rather than a lazy iterable.
evens1 = [x for x in range(10) if x % 2 == 0]
evens2 = list(map(filter(range(10), lambda x: x % 2 == 0), lambda x: x))
Correspondingly in your own code, you could evaluate the map
result to a list and then discard it immediately; that would also work.
result: list = []
list(map(result.append, [x for x in range(10) if x % 2 == 0]))
#^^^
print(result)
(In the setup you show, result
is expected to be identical to the input list. More generally you can use map
or a list comprehension instead of iterating and using result.append
, and this more functional style may be a little more compact and easier to read.)
Upvotes: 2
Reputation: 23250
Of course, a list comprehension evaluates to a list, which is an iterable suitable for map
.
The problem in your case is that the iterator returned by map
is never used, so result.append
is never called.
Upvotes: 4