知识点:
每当python访问一个变量、函数或模块时,都有一个体系来决定它去哪里查找这些对象。
首先,python会查找 locals()数组,其内保存了所有本地变量的条目。
如果不在locals()里,会去搜索globals()字典,
最后会搜索__builtin__对象。
举例:
import math
from math import sin
def test1(x):
return math.sin(x)
def test2(x):
return sin(x)
def test3(x, sin=math.sin):
return sin(x)
#分别运行1000000以上三个方法,
test1:3:381ns
test2:3:311ns
test3:3:306ns
我们分别用dis模块解析函数的调用
dis.dis(test1) math -> sin
dis.dis(test2) sin
dis.dis(test3) sin
test1显示查询math库来调用sin。我们可以根据dis看出,首先一个math模块的引用必须被调用,然后在模块上进行属性查询,知到找到sin函数。整个步骤进行了两次字典查询,一次查找math模块,一次在模块中查找sin函数。
test2从math模块显式导入了sin函数,因此该函数可在全局命名空间中直接被访问。这意味着我们可以避免查询math模块以及后续的属性查询,我们只需要从全局命名空间中查找sin函数。
test3定义了sin函数作为一个参数的关键字,其默认值是math模块的sin函数的引用。虽然我们依然需要在模块中查找这一个函数,但仅在test3函数第一次被定义时查找。之后,这一引用以默认参数关键字的形式作为一个本地变量被保存在函数定义中。本地变量无需字典查询,他们被保存在一个十分微小的数组中,查询速度快。
优化:
在循环中降低命名空间的查询速度(循环较大):
from math import sin
def test1(x):
result = 0
for i in xrange(x):
result += sin(i)
#优化代码
def test2(x):
result = 0
local_sin = sin
for i in xrange(x):
result += local_sin(i)