Python列表和字典的性能怎么样
Admin 2022-07-05 群英技术资讯 487 次浏览
对比 list 和 dict 操作如下:
List列表数据类型常用操作性能:
最常用的是:按索引取值和赋值(v=a[i],a[i]=v),由于列表的随机访问特性,这两个操作执行时间与列表大小无关,均为O(1)。
另一个是列表增长,可以选择 append() 和 “+”:lst.append(v),执行时间是O(1);lst= lst+ [v],执行时间是O(n+k),其中 k 是被加的列表长度,选择哪个方法来操作列表,也决定了程序的性能。
测试 4 种生成 n 个整数列表的方法:
创建一个 Timer 对象,指定需要反复运行的语句和只需要运行一次的"安装语句"。
然后调用这个对象的 timeit 方法,指定反复运行多少次。
# Timer(stmt="pass", setup="pass") # 这边只介绍两个参数 # stmt:statement的缩写,就是要测试的语句,要执行的对象 # setup:导入被执行的对象(就和run代码前,需要导入包一个道理) 在主程序命名空间中 导入 time1 = Timer("test1()", "from __main__ import test1") print("concat:{} seconds".format(time1.timeit(1000))) time2 = Timer("test2()", "from __main__ import test2") print("append:{} seconds".format(time2.timeit(1000))) time3 = Timer("test3()", "from __main__ import test3") print("comprehension:{} seconds".format(time3.timeit(1000))) time4 = Timer("test4()", "from __main__ import test4") print("list range:{} seconds".format(time4.timeit(1000))
结果如下:
可以看到,4种方法运行时间差别挺大的,列表连接(concat)最慢,List range最快,速度相差近 100 倍。append要比 concat 快得多。另外,我们注意到列表推导式速度大约是 append 两倍的样子。
总结列表基本操作的大 O 数量级:
我们注意到 pop 这个操作,pop()是从列表末尾移除元素,时间复杂度为O(1);pop(i)从列表中部移除元素,时间复杂度为O(n)。
原因在于 Python 所选择的实现方法,从中部移除元素的话,要把移除元素后面的元素,全部向前挪位复制一遍,这个看起来有点笨拙
但这种实现方法能够保证列表按索引取值和赋值的操作很快,达到O(1)。这也算是一种对常用和不常用操作的折中方案。
list.pop()的计时试验,通过改变列表的大小来测试两个操作的增长趋势:
import timeit pop_first = timeit.Timer("x.pop(0)", "from __main__ import x") pop_end = timeit.Timer("x.pop()", "from __main__ import x") print("pop(0) pop()") y_1 = [] y_2 = [] for i in range(1000000, 10000001, 1000000): x = list(range(i)) p_e = pop_end.timeit(number=1000) x = list(range(i)) p_f = pop_first.timeit(number=1000) print("{:.6f} {:.6f}".format(p_f, p_e)) y_1.append(p_f) y_2.append(p_e)
结果如下:
将试验结果可视化,可以看出增长趋势:pop()是平坦的常数,pop(0)是线性增长的趋势。
字典与列表不同,是根据键值(key)找到数据项,而列表是根据索引(index)。最常用的取值和赋值,其性能均为O(1)。另一个重要操作contains(in)是判断字典中是否存在某个键值(key),这个性能也是O(1)。
做一个性能测试试验来验证 list 中检索一个值,以及 dict 中检索一个值的用时对比,生成包含连续值的 list 和包含连续键值 key 的
dict,用随机数来检验操作符 in 的耗时。
import timeit import random y_1 = [] y_2 = [] print("lst_time dict_time") for i in range(10000, 1000001, 25000): t = timeit.Timer("random.randrange(%d) in x" % i, "from __main__ import random, x") x = list(range(i)) lst_time = t.timeit(number=1000) x = {j: 'k' for j in range(i)} dict_time = t.timeit(number=1000) print("{:.6f} {:.6f}".format(lst_time, dict_time)) y_1.append(lst_time) y_2.append(dict_time)
结果如下:
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
with从Python 2 5就有,需要from __future__ import with_statement。自python 2 6开始,成为默认关键字。也就是说with是一个控制流语
内容介绍一、问题背景二、Canny算法(一)、高斯平滑(二)Sobel算子计算梯度(三)非极大化抑制(四)滞后边缘跟踪一、问题背景纸面上有一枚一元钱的银币,你能在Canny和Hough的帮助
用Python怎样将日历与时间转换,方法和代码是什么?有不少朋友对此感兴趣,下面小编给大家整理和分享了相关知识和资料,易于大家学习和理解,有需要的朋友可以借鉴参考,下面我们一起来了解一下吧。
这篇文章主要为大家详细介绍了Python实现环形链表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
这篇文章主要为大家介绍了python计算机视觉opencv矩形轮廓顶点位置确定,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008