性能比较:插入与构建Python集操作
在python中,使用 a) 从n个项目的列表构建一个集合 b) 在一个集合中插入n项 我找到了这一页(http://wiki.python.org/moin/TimeComplexity)但它没有足够的信息来断定哪个更快 看起来,在最坏的情况下,一次插入一个项目可能需要O(n*n)个时间(假设它使用dicts),在平均情况下需要O(n*1)。用列表初始化集合是否有任何性能改进?在复杂性方面-这肯定是相同的,因为两种方法的作用完全相同-在集合中插入性能比较:插入与构建Python集操作,python,set,time-complexity,Python,Set,Time Complexity,在python中,使用 a) 从n个项目的列表构建一个集合 b) 在一个集合中插入n项 我找到了这一页(http://wiki.python.org/moin/TimeComplexity)但它没有足够的信息来断定哪个更快 看起来,在最坏的情况下,一次插入一个项目可能需要O(n*n)个时间(假设它使用dicts),在平均情况下需要O(n*1)。用列表初始化集合是否有任何性能改进?在复杂性方面-这肯定是相同的,因为两种方法的作用完全相同-在集合中插入n项 不同之处在于实现:从iterable初始化
n
项
不同之处在于实现:从iterable初始化的一个明显优势是,可以节省大量Python级别的函数调用—从iterable初始化完全在C级别(**)上完成
事实上,对500万个随机整数的列表进行的一些测试表明,逐个相加的速度较慢:
lst = [random.random() for i in xrange(5000000)]
set1 = set(lst) # takes 2.4 seconds
set2 = set() # takes 3.37 seconds
for item in lst:
set2.add(item)
(**)查看集合代码(
Objects/setobject.c
),最终项目插入归结为调用set\u add\u key
。从iterable初始化时,在紧密C循环中调用此函数:
while ((key = PyIter_Next(it)) != NULL) {
if (set_add_key(so, key) == -1) {
Py_DECREF(it);
Py_DECREF(key);
return -1;
}
Py_DECREF(key);
}
另一方面,对
set.add
的每次调用都会调用属性查找,这将解析为Cset\u add
函数,该函数依次调用set\u add\u key
。由于项添加本身相对较快(Python的哈希表实现非常高效),因此这些额外调用都会累积。以下是使用timeit
运行比较的结果。似乎set using list的初始化速度更快,想知道为什么会这样:
from timeit import timeit
timeit("set(a)","a=range(10)")
# 0.9944498532640864
timeit("for i in a:x.add(i)","a=range(10);x=set()")
# 1.6878826778265648
Python版本:2.7在我的Thinkpad上:
$ python -V
Python 2.5.2
$ python -m timeit -s "l = range(1000)" "set(l)"
10000 loops, best of 3: 64.6 usec per loop
$ python -m timeit -s "l = range(1000)" "s = set()" "for i in l:s.add(i)"
1000 loops, best of 3: 307 usec per loop
In [37]: timeit.timeit('for a in x: y.add(a)',
'y=set(); x=range(10000)', number=10000)
Out[37]: 12.18006706237793
In [38]: timeit.timeit('y=set(x)', 'y=set(); x=range(10000)', number=10000)
Out[38]: 3.8137960433959961
似乎您想将从列表中构建一个集合与插入n个要设置的项进行比较,但第一行问题的意思有所不同。哎呀!感谢您指出sateesh。使用
timeit
,您很容易找到它。Python循环的性能比我预期的更接近,您可以通过创建一个包含对set的引用的局部变量来更接近它。添加并在循环中调用它,避免属性查找。在我的测试中,这只比使用set()
构造函数慢15%左右!通过s_add=s.add
:python-m timeit-s“l=range(1000)”“s=set();s_add=s.add”“对于l:s_add(i)”,可以将第二个命令的速度提高2倍。