Python:为什么将函数名称复制到本地名称空间会导致访问速度更快

aza*_*aks 5 python

从这里的代码:https://www.learnsteps.com/increasing-performance-python-code/

import datetime 
alist = [str(x) for x in range(100000000)]

print("\nStandard loop.") 
a = datetime.datetime.now() 
result = [] 
for item in alist: 
    result.append(len(item)) 
b = datetime.datetime.now() 
print((b-a).total_seconds()) 

print("\nStandard loop with function name in local namespace.") 
a = datetime.datetime.now() 
result = [] 
fn = len 
for item in alist:
    result.append(fn(item))
b = datetime.datetime.now()
print((b-a).total_seconds())

print("\nUsing map.")
a = datetime.datetime.now()
result = list(map(len, alist))
b = datetime.datetime.now()
print((b-a).total_seconds())

print("\nUsing map with function name in local namespace.")
a = datetime.datetime.now() 
fn = len 
result = list(map(fn, alist)) 
b = datetime.datetime.now() 
print((b-a).total_seconds()) 

print("\nList comprehension.") 
a = datetime.datetime.now() 
result = [len(i) for i in alist] 
b = datetime.datetime.now() 
print((b-a).total_seconds()) 
print("\nList comprehension with name in local namespace.") 

a = datetime.datetime.now() 
fn = len 
result = [fn(i) for i in alist] 
b = datetime.datetime.now() 
print((b-a).total_seconds())
Run Code Online (Sandbox Code Playgroud)

产生这个输出:

Standard loop.
20.862797

Standard loop with function name in local namespace.
16.34087

Using map.
6.893764

Using map with function name in local namespace.
6.774654

List comprehension.
9.362831

List comprehension with name in local namespace.
10.007393
Run Code Online (Sandbox Code Playgroud)

有人能提供比'函数查找成本高'更好的解释,为什么创建一个接近函数使用的函数原型更快?(这对大多数函数都不起作用,通常只在紧密循环中,但为什么会发生这种情况呢?)

blh*_*ing 4

这是因为名称解析首先从本地命名空间开始,如果本地没有找到,就会在下一个最近的封闭代码块中查找,然后再到下一个最近的封闭代码块中查找,直到模块代码块,即是全局命名空间,如果在全局命名空间中找不到该名称,那么解释器才会查找内置名称。这就是为什么将对内置名称的引用分配len给全局名称fn会加速代码示例中的名称解析的原因。