0

Why is this returning an empty list:

def word_lengths(phrase):

    result = []
    map(lambda x: result.append(x) , phrase.split())
    return result

Where as this returns a list of the length of each word in the phrase:

def word_lengths(phrase):

    return list(map(lambda x: len(x) , phrase.split()))
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
smackenzie
  • 2,880
  • 7
  • 46
  • 99
  • Please provide an example input (phrase) and expected output vs real output. – Nir Alfasi Nov 29 '17 at 00:19
  • Note that `lambda x: len(x)` is just a more complicated way of saying `len`, and that the whole thing would be more pythonically expressed as a list comprehension: `[len(word) for word in phrase.split()]`. – mkrieger1 Nov 29 '17 at 00:24
  • Possible duplicate of [Python 3 map dictionary update method to a list of other dictionaries](https://stackoverflow.com/questions/30000391/python-3-map-dictionary-update-method-to-a-list-of-other-dictionaries) (it's about `dict.update`, not `list.append`, but everything else about it is the same) – ShadowRanger Nov 29 '17 at 01:12
  • For one, you're not assigning that `map` call to anything in the former case. And even calling `list(map(...` with the `result.append(x)` as your lambda will just return a list of `None` for as many elements as there are in `phrase.split()` – blacksite Nov 29 '17 at 01:24

1 Answers1

3

In Python 3, map results in a generator, which is lazily evaluated.

You need to iterate over it to take effect, for example by calling the list constructor on it:

result = []
list(map(lambda x: result.append(x) , phrase.split()))
return result

This mutates result as you had probably expected.

Note though, that the same can be achieved in a much simpler way:

return phrase.split()
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
  • 1
    Returning `phrase.split()` directly is *much* more Pythonic. Abusing `map` for side-effects is profoundly misunderstanding the point of functional programming idioms. `map` (and list comprehensions and generator expressions) should always be side-effect free, to avoid lots of spooky action at a distance that makes it hard to reason about the code. – ShadowRanger Nov 29 '17 at 01:06
  • 2
    Also, side-note: For the *extremely* rare cases where using `map` for side-effects makes sense (usually using the `multiprocessing` `map`-like functions to parallelize a task), the best way to force it to run to completion is to wrap it in a `collections.deque` constructor with a `maxlen` of `0` (which is optimized to run iterators to exhaustion without storing a thing), e.g. `collection.deque(map(...), 0)` which would avoid making a potentially large temporary `list` of `None`s for no purpose. – ShadowRanger Nov 29 '17 at 01:09
  • I appreciate the side effect comment, and that phrase.split() is a much easier way to do it. It was a project question on a python course to understand maps, and I just had an idea about whether or not you could update an external list within the lambda...purely academic. – smackenzie Nov 29 '17 at 14:01