考虑以下代码片段:
dict [name] = 0
dict [name] += 1
dict [name] += 1
Python解释器是否自动识别对字典值的重复引用并使用缓存的本地引用,有点类似于C/C++的别名优化,变成了这样:
value = dict [name]
value = 0
value += 1
value += 1
显然,手动完成这项任务并不是什么大问题,但我很好奇是否真的有必要这样做。欢迎任何见解、反馈等。
考虑以下代码片段:
dict [name] = 0
dict [name] += 1
dict [name] += 1
Python解释器是否自动识别对字典值的重复引用并使用缓存的本地引用,有点类似于C/C++的别名优化,变成了这样:
value = dict [name]
value = 0
value += 1
value += 1
显然,手动完成这项任务并不是什么大问题,但我很好奇是否真的有必要这样做。欢迎任何见解、反馈等。
import dis
def test():
name = 'test'
tdict = {}
tdict[name] = 0
tdict[name] += 1
tdict[name] += 1
dis.dis(test)
运行它,我们得到:
13 0 LOAD_CONST 1 ('test')
3 STORE_FAST 0 (name)
14 6 BUILD_MAP 0
9 STORE_FAST 1 (tdict)
15 12 LOAD_CONST 2 (0)
15 LOAD_FAST 1 (tdict)
18 LOAD_FAST 0 (name)
21 STORE_SUBSCR
16 22 LOAD_FAST 1 (tdict)
25 LOAD_FAST 0 (name)
28 DUP_TOPX 2
31 BINARY_SUBSCR
32 LOAD_CONST 3 (1)
35 INPLACE_ADD
36 ROT_THREE
37 STORE_SUBSCR
17 38 LOAD_FAST 1 (tdict)
41 LOAD_FAST 0 (name)
44 DUP_TOPX 2
47 BINARY_SUBSCR
48 LOAD_CONST 3 (1)
51 INPLACE_ADD
52 ROT_THREE
53 STORE_SUBSCR
54 LOAD_CONST 0 (None)
57 RETURN_VALUE
看起来,在这种情况下,LOAD_FAST
每次尝试访问以执行递增操作时都会加载tdict
和name
的值,因此答案似乎是否定的。
仅通过检查代码是无法进行这种类型的优化的。你的名称dict
可能不是指本地字典,而是指实现了__setitem__
的用户定义对象,并且必须调用该方法三次。在运行时,一个复杂的实现可以注意到名称的实际值,并进行优化,但是在运行之前无法进行优化,否则会破坏一些Python语义。
>>> a = {}
>>> name = 'x'
>>> a[name] = 0
>>> a[name] += 1
>>> a[name] += 1
>>> a[name] # ok no suprises so far
2
>>> a = {}
>>> a[name] = 0
>>> x = a[name] # x is now literally `0`, not some sort of reference to a[name]
>>> x
0
>>> x += 1
>>> x += 1
>>> a[name] # so this never changed
0
>>>
Python 没有类似 C 的“引用(reference)”概念。你在想的那个用法只能适用于可变类型,比如 list
。这是 Python 很基础的一点,当你使用 Python 编程时,应该忘掉 C 传授给你的关于变量的所有知识。
将你的两个例子改成类似于这样:
#v1.py
di = {}
name = "hallo"
di[name] = 0
for i in range(2000000):
di[name] += 1
和
#v2.py
di = {}
name = "hallo"
di[name] = 0
value = di[name]
for i in range(2000000):
value += 1
$ time python2.7 v1.py
real 0m0.788s
user 0m0.700s
sys 0m0.080s
$ time python2.7 v2.py
real 0m0.586s
user 0m0.490s
sys 0m0.090s
$ time pypy v1.py
real 0m0.203s
user 0m0.210s
sys 0m0.000s
$ time pypy v2.py
real 0m0.117s
user 0m0.080s
sys 0m0.030s
所以,为单个解释器优化代码并不好(例如我没有测试过Jython...),但当有人优化解释器时,这是很棒的...