I was very surprised that a seemingly easier and less taxing function was less efficient.
I ran a test on two methods, with a 10000 a-j (randomized) characters long string as word. The old function is a, the new one is b:
def a(word):
dictionary = {"a": 1, "b": 2, "c": 3, "d": 4, "e": 5, "f": 6, "g": 7, "h": 8, "i": 9, "j": 10,}
word = list(map(dictionary.get, list(word)))
return word
def b(word):
dictionary = {"a": 1, "b": 2, "c": 3, "d": 4, "e": 5, "f": 6, "g": 7, "h": 8, "i": 9, "j": 10,}
word = [dictionary.get(l, l) for l in word]
return word
map is supposed to have a tiny speed advantage vs a for loop: https://stackoverflow.com/a/1247490/12494235. However, in my case, the advantage is significant. Many more operations are being executed in function b, and it consistently takes 0.001-0.003 seconds longer. Also, converting the map iterable into a list should slow down a.
A - creating a list from a map using dictionary get() as a function
         160 function calls (159 primitive calls) in 0.002 seconds
   Ordered by: call count
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       12    0.000    0.000    0.000    0.000 {method 'rstrip' of 'str' objects}
        7    0.000    0.000    0.000    0.000 {method 'join' of 'str' objects}
        6    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:222(_verbose_message)
        6    0.000    0.000    0.000    0.000 {built-in method builtins.getattr}
        ...
B - creating a dictionary get() list with a for loop
         10161 function calls (10160 primitive calls) in 0.004 seconds
   Ordered by: call count
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    10002    0.001    0.000    0.001    0.000 {method 'get' of 'dict' objects}
       12    0.000    0.000    0.000    0.000 {method 'rstrip' of 'str' objects}
        7    0.000    0.000    0.000    0.000 {method 'join' of 'str' objects}
        6    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:222(_verbose_message)
        6    0.000    0.000    0.000    0.000 {built-in method builtins.getattr}
        ...
How is that even possible? Did I do something wrong when profiling the two? Why is a for loop so inefficient?
 
    