我很惊讶,一个看似更简单、更省事的函数却效率更低。
我对两种方法进行了测试,将10000个a-j(随机(字符长的字符串作为word
旧函数为a
,新函数为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
被认为与for循环相比具有微小的速度优势:https://stackoverflow.com/a/1247490/12494235.然而,就我而言,优势是显著的。函数b
中执行了更多的操作,并且始终需要0.001-0.003秒的时间。此外,将映射可迭代转换为列表应该会降低a
的速度。
A-使用dictionary get((作为函数从地图创建列表
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-使用for循环创建字典get((列表
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}
...
这怎么可能?我在分析两者时做错了什么吗?为什么for循环如此低效
例如,如果有arr1
和arr2
,则长度都为n
=10^9。
def A:
for i in range(n):
arr1[i] = 1
arr2[i] = 2
def B:
for i in range(n):
arr1[i] = 1
for i in range(n):
arr2[i] = 2
你应该认为A
应该比B
快,但它不是。。。因为在A
的情况下,编译器需要在每个iter
中从arr1 ptr
跳到arr2 ptr
。甚至B
也有2个for,但操作一开始只对arr1调用,然后只对arr2调用——效率很高。因此,一切都取决于该方法是如何实现的,编译器是如何工作的,或者处理什么对象,以及它是如何保存在内存中的。希望你能理解for loop
为什么效率这么低。。。