0

The best way to build efficiently is to understand the toolkit one is building with. However, while trying to understand the core functions of python, it occurred to me that the map function gave similar, if not the same, results as a generic generator expression.

Take the next bit of code as a simplified example. These two objects, mapped and generated, behave astoundingly similar in whatever situation you throw them.

def concatenate(string1 = "", string2 = ""):
    return string1.join(" ", string2)

foo = ["One", "Two"]
bar = ["Blue", "Green"]

mapped = map(concatenate, foo, bar)
generated = (concatenate(string1 = a, string2 = b) for a, b in zip(foo, bar))

Okay, I know that it is a longer line of code, but I find it hard to believe that's all of map's reason of existence, so in my quest to understand python. What does map still do in python? Is it really just a relic of olden times, and if not, where can I best put this tool to use?

  • Map was basically replaced with list comprehension. It still as some uses (for special cases) but it has primarily been replaced with list comprehension in python 3. There are people that prefer to use map because that is what they are familiar with but basically its just legacy. – Error - Syntactical Remorse May 19 '19 at 00:04
  • Hmm, but then doesn't that break with the zen of pythons' line: "There should be one-- and preferably only one --obvious way to do it." And if that is the case, then why didn't the developers choose to exclude it in python 3? Keeping it then only adds to the confusion. May I ask what special cases though? – alderuijter May 19 '19 at 12:26

1 Answers1

0

The reason both exist is because list comprehension returns a new list where as map (in Python3) returns a generator thus map is more memory efficient if you don't need the resulting list right away.

This can be considered a technicality though since often when you use list comprehension to do something a map can do, you overwrite the original variable:

a = [1, 2, 3]
# The following line creates a new list but
# since we assign that list to `a` we give the old list to 
# the garbage collector
a = [x**2 for x in a]
# or
a = list(map(lambda x: x**2, a))
# both of which are basically the same.

The power of map can come into play if you aren't working with the same variable:

a = [1, 2, 3] # If we want to save this then we don't want to overwrite it
b = [x**2 for x in a] # A full new list is now in b
c = map(lambda x: x**2, a) # c is just a generator object.
print(a) # [1, 2, 3]
print(b) # [1, 4, 9]
print(c) # <map object ...>
for x in c:
    print(x) 
    # We never create a full list from c, we just use each object as we go thus we save memory.

In the previous example b is a whole new list of memory where as c is just a generator object. When working with such a small a, b and c are probably pretty close in memory but if a was large c would be significantly less memory than b.

Most common use cases of map involve the first case, thus map has no real benefit but in the second case it is much more beneficial to use map.

For the record "one way to do something" from the zen is sorta vague. I could implement a merge sort the right way (i.e. perfect speed and space) but my code my look completely different then someone else who implemented merge sort. "one way" doesn't really mean only one way to code it, it more implies there is only one methodology to be used or one process.

  • First of all, thanks for the extensive answer and forgive me for not accepting it yet. However, a question still remains to me. Mind if I ask? Indeed when using list comprehension, it creates a list. However, how is map any different from using generator comprehension, eg. replacing the square brackets with round brackets? As that will create a similar, if not the same, object... – alderuijter May 20 '19 at 06:54
  • Ah, that is indeed an interesting view on that specific line of the zen of python. I once heard the saying: "In Python, one line of logic equals one line of code. When looking at the zen from that perspective, I feel the line means that there shouldn't be two easy, obvious ways to accomplish the same line of logic, thus avoiding mental struggle for the coder and the reader of the code when reading the code. – alderuijter May 20 '19 at 07:07
  • Good question that I forgot to cover. See https://stackoverflow.com/q/1247486/8150685 – Error - Syntactical Remorse May 20 '19 at 11:47
  • That indeed cleared the rest of my confusion, thank you for your time and effort! – alderuijter May 20 '19 at 14:47