在尝试解决更复杂的问题时,我开始将访问速度与局部变量与成员变量进行比较。
这是一个测试程序:
#!/usr/bin/env python
MAX=40000000
class StressTestMember(object):
def __init__(self):
self.m = 0
def do_work(self):
self.m += 1
self.m *= 2
class StressTestLocal(object):
def __init__(self):
pass
def do_work(self):
m = 0
m += 1
m *= 2
# LOCAL access test
for i in range(MAX):
StressTestLocal().do_work()
# MEMBER access test
for i in range(MAX):
StressTestMember().do_work()
我知道在每次迭代中实例化StressTestMember
和StressTestLocal
可能看起来不错,但在建模程序中这些基本上是活动记录是有意义的。
经过简单的基准测试后,
本地版本的速度提高约33%,同时仍然是课程的一部分。为什么呢?
答案 0 :(得分:25)
self.m += 1
表示您必须查找名为self
的本地变量,然后找到名为m
的属性
当然,如果你只需要查找一个局部变量,没有额外的步骤就会更快。
了解幕后发生的事情会很有用:
>>> import dis
>>> dis.dis(StressTestLocal.do_work)
18 0 LOAD_CONST 1 (0)
3 STORE_FAST 1 (m)
19 6 LOAD_FAST 1 (m)
9 LOAD_CONST 2 (1)
12 INPLACE_ADD
13 STORE_FAST 1 (m)
20 16 LOAD_FAST 1 (m)
19 LOAD_CONST 3 (2)
22 INPLACE_MULTIPLY
23 STORE_FAST 1 (m)
26 LOAD_CONST 0 (None)
29 RETURN_VALUE
>>> dis.dis(StressTestMember.do_work)
10 0 LOAD_FAST 0 (self)
3 DUP_TOP
4 LOAD_ATTR 0 (m)
7 LOAD_CONST 1 (1)
10 INPLACE_ADD
11 ROT_TWO
12 STORE_ATTR 0 (m)
11 15 LOAD_FAST 0 (self)
18 DUP_TOP
19 LOAD_ATTR 0 (m)
22 LOAD_CONST 2 (2)
25 INPLACE_MULTIPLY
26 ROT_TWO
27 STORE_ATTR 0 (m)
30 LOAD_CONST 0 (None)
33 RETURN_VALUE
答案 1 :(得分:6)
本地名称更快,因为Python做了一些优化,本地名称不需要dict访问,另一方面,实例属性需要访问对象的__dict__
。
这也是本地名称比全局名称更快的原因。