dea*_*nik 4 python performance set python-2.7
我在python 2.7.6中运行了以下小测试:
s = set(xrange(0, 1000000))
for i in xrange(0, 5000000):
if s.__contains__(i):
pass
Run Code Online (Sandbox Code Playgroud)
并获得以下运行输出time python py.py:
real 0m0.616s
Run Code Online (Sandbox Code Playgroud)
然后我将我的代码更改为:
s = set(xrange(0, 1000000))
for i in xrange(0, 5000000):
if i in s:
pass
Run Code Online (Sandbox Code Playgroud)
并得到了运行时间0.467s.我也得到了相同的结果dict.我的问题是"为什么存在性能差异?",也许是python如何执行s.__contains__(i)和调用的一些解释i in s
Mar*_*ers 10
使用时,s.__contains__(i)您需要在Python中进行属性查找,以及在Python中进行方法调用.这些作为单独的字节码执行:
>>> import dis
>>> dis.dis(compile('s.__contains__(i)', '<>', 'exec'))
1 0 LOAD_NAME 0 (s)
3 LOAD_ATTR 1 (__contains__)
6 LOAD_NAME 2 (i)
9 CALL_FUNCTION 1
12 POP_TOP
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
LOAD_ATTR加载该__contains__属性,CALL_FUNCTION然后执行该方法.
使用i in s只需一个字节码:
>>> dis.dis(compile('i in s', '<>', 'exec'))
1 0 LOAD_NAME 0 (i)
3 LOAD_NAME 1 (s)
6 COMPARE_OP 6 (in)
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
这里COMPARE_OP完成所有工作.
在C中,然后,查找__contains__插槽(或者更确切地说,它的C等价物)并调用它要快得多.
请注意,在比较Python中的两种方法时,使用timeit模块而不是UNIX time命令要好得多; 它会尝试消除环境因素并为您重复测试:
>>> import timeit, random
>>> testset = {random.randrange(50000) for _ in xrange(1000)}
>>> tests = [random.randrange(5000) for _ in xrange(500)]
>>> timeit.timeit('for i in tests: i in s',
... 'from __main__ import testset as s, tests',
... number=100000)
2.5375568866729736
>>> timeit.timeit('for i in tests: s.__contains__(i)',
... 'from __main__ import testset as s, tests',
... number=100000)
4.208703994750977
Run Code Online (Sandbox Code Playgroud)
使用__contains__速度慢一些距离.