下面的第0个循环比第1个循环运行得快得多(Python-2.7为3倍,Python-3.4为5倍):
for x in range(0,999999):
"u" in {"a", "e", "i", "o", "u"}
for x in range(0,999999):
"u" in set("aeiou")
似乎Python在给定{"a", "e", "i", "o", "u"}
时构建了一次集合,但是当给定set("aeiou")
时,每次需要时都会构建集合。
这是对的吗?如果是这样,为什么Python不优化后者?
* 使用time python -c '<code>'
答案 0 :(得分:1)
您在每个循环中调用构造函数。再试一次:
canvasImg.toDataURL( "image/jpeg", 1.0 )
这给出了时间:
import time
start = time.time()
for x in range(0,999999):
"u" in {"a", "e", "i", "o", "u"}
print time.time() - start, "for dictionary look-up"
start = time.time()
for x in range(0,999999):
"u" in ["a", "e", "i", "o", "u"]
print time.time() - start, "for list look-up" start = time.time()
for x in range(0,999999):
"u" in set("aeiou")
print time.time() - start, "for set construction"
start = time.time()
vowel = set("aeiou")
for x in range(0,999999):
"u" in vowel
print time.time() - start, "for set reference"
答案 1 :(得分:1)
我根据你的片段(分别来自#0和#1)创建了函数f1和f2。然后我使用dis模块。简而言之,您可以看到在循环内的第二种情况下调用了集合构造函数(第二种情况中为31)。而一个常数只是在第一个中加载(第一个中的25个)。
In [20]: dis.dis(f1)
2 0 SETUP_LOOP 33 (to 36)
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (0)
9 LOAD_CONST 2 (999999)
12 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
15 GET_ITER
>> 16 FOR_ITER 16 (to 35)
19 STORE_FAST 0 (x)
3 22 LOAD_CONST 3 ('u')
25 LOAD_CONST 8 (frozenset({'e', 'o', 'a', 'u', 'i'}))
28 COMPARE_OP 6 (in)
31 POP_TOP
32 JUMP_ABSOLUTE 16
>> 35 POP_BLOCK
>> 36 LOAD_CONST 0 (None)
39 RETURN_VALUE
In [21]: dis.dis(f2)
2 0 SETUP_LOOP 39 (to 42)
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (0)
9 LOAD_CONST 2 (999999)
12 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
15 GET_ITER
>> 16 FOR_ITER 22 (to 41)
19 STORE_FAST 0 (x)
3 22 LOAD_CONST 3 ('u')
25 LOAD_GLOBAL 1 (set)
28 LOAD_CONST 4 ('aeiou')
31 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
34 COMPARE_OP 6 (in)
37 POP_TOP
38 JUMP_ABSOLUTE 16
>> 41 POP_BLOCK
>> 42 LOAD_CONST 0 (None)
45 RETURN_VALUE
答案 2 :(得分:1)
Python解释器不会将set("aeiou")
识别为常量,因为尽管告诉"aeiou"
不会发生变化这一点很简单,但要难得多判断set
函数是否会改变。
解释器可以检查set()
是否未在循环内的任何位置重新分配,但我想麻烦不值得。
答案 3 :(得分:0)
在第一种情况下,您在编译时创建一次集合(当python代码编译为python byte-ops时)。在第二个中,你为循环的每次迭代创建一次。