Python列表和字典的性能怎么样
Admin 2022-07-05 群英技术资讯 520 次浏览
对比 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进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
当我们用python进行数据处理时会遇到很多缺失值,缺失值一般是由于我们所处理的数据本身的特性、当初录入的失误或者其它原因导致的,下面这篇文章主要给大家介绍了关于pandas返回缺失值位置的方法,需要的朋友可以参考下
本文给大家分享Python 实时获取任务请求对应的Nginx日志的方法,本文通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
这篇文章主要介绍了Python中的内置函数isdigit(),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
ajax与django交互怎样实现?一些新手对于ajax与django的交互并不是很理解,下面小编就给大家介绍关于ajax与django交互的相关内容供大家参考学习,感兴趣的朋友们可以看看。
在日常开发中,对数据进行序列化和反序列化是常见的数据操作,Python提供了两个模块方便开发者实现数据的序列化操作,即 json 模块和 pickle 模块。本文就为大家详细讲解这两个模块的使用,需要的可以参考一下
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008