前言
今天看到一些关于容器的使用技巧,这里分享给大家,一起提高python编程能力
文末领取Python全套最新学习资源
列表性能陷阱
陷阱一
列表中插入数据,我们通常使用append()方法在尾部追加,也可以使用insert()在任意位置插入。但是当数据量比较大时,有些操作会变的很慢。我们测验一下
def list_append():
"""不断往尾部追加"""
l = []
for i in range(5000):
l.append(i)
def list_insert():
"""不断往头部插入"""
l = []
for i in range(5000):
l.insert(0, i)
使用timeit模块进行测试,
import timeit
append_spent = timeit.timeit(list_append, number=1000)
print("list_append:", append_spent) # list_append: 0.30923892399999997
insert_spent = timeit.timeit(list_insert, number=1000)
print("list_insert", insert_spent) # list_insert 5.752398332
通过结果,可以看到,list_append和list_insert两个函数都是构建长度为5000的列表,list_insert比list_append耗时多达18倍。这是因为,列表的底层是数组,在数组中间插入成员时,这个成员之后的成员都需要移动位置,这个操作的平均时间复杂度是O(n),而在尾部插入,这个操作的平均时间复杂度是O(1)。
那如何解决该性能问题呢?
我们可以使用collections.deque来代替列表,像这样
from collections import deque
def deque_append():
"""不断往尾部追加"""
l = deque()
for i in range(5000):
l.append(i)
def deque_insert():
"""不断往头部插入"""
l = deque()
for i in range(5000):
l.insert(0, i)
我们使用deque实现了同样的逻辑,我们再来测试一下
import timeit
append_spent = timeit.timeit(deque_append, number=1000)
print("deque_append:", append_spent) # deque_append: 0.300922523
insert_spent = timeit.timeit(deque_insert, number=1000)
print("deque_insert", insert_spent) # deque_insert 0.47996506299999997
通过结果可以看到,使用deque,不论从尾部还是从头部追加成员都非常快。
陷阱二
判断成员是否在列表中存在,像这样
nums = list(range(1000000))
def is_True():
return 1000000 in nums
我们还是使用timeit来测试一下
import timeit
spent = timeit.timeit(is_True, number=1000)
print("is_True:", spent) # is_True: 10.706976014
可以看到耗时很长,这是因为,判断某个成员是否存在,只能从前往后遍历所有成员,这个操作的平均时间复杂度是O(n)。
那该如何解决该性能问题吗?
可以考虑将列表转换成集合类型,像这样
nums = list(range(1000000))
nums_set = set(nums)
def is_True():
return 1000000 in nums_set
我们再测试一下,
import timeit
spent = timeit.timeit(is_True, number=1000)
print("is_True:", spent) # is_True: 0.00022141500000000258
可以看到速度很快,这是因为,在集合底层使用了哈希表数据结构,判断某个成员是否存在,只需算出该成员的哈希值,然后去哈希表对应位置检查obj是否存在就可以了,这个操作的平均时间复杂度是O(1)
快速合并字典
提到合并字典,我们想到最简单的方法,就是使用update方法
d1 = {"name": "honey"}
d2 = {"age": 18}
d1.update(d2)
print(d1) # {'name': 'honey', 'age': 18}
这有一个缺陷,修改了字典d1原始内容。那该如何解决呢?我们可以使用动态解包表达式
d1 = {"name": "honey"}
d2 = {"age": 18}
print({**d1, **d2}) # {'name': 'honey', 'age': 18}
print(d1) # {'name': 'honey'}
解包过程会进行浅拷贝操作
通过有序字典去重
给定一个列表,我们去重,会想到使用集合
nums = [10, 2, 3, 3, 51, 5, 10, 7, 8, 5]
print(set(nums)) # {2, 3, 5, 7, 8, 10, 51}
很容易就去重了,但是如果我们要求,去重并且要保留成员原有的顺序呢?此时我们可以使用有序字典来实现
from collections import OrderedDict
nums = [10, 2, 3, 3, 51, 5, 10, 7, 8, 5]
print(list(OrderedDict.fromkeys(nums).keys())) # [10, 2, 3, 51, 5, 7, 8]
OrderedDict可以保证键是有序的且不会重复
最后
这些技巧还是很实用的,看似是技巧,实则需要了解容器的底层,才能理解使用这些技巧。
以上就是今天的全部内容分享,觉得有用的话欢迎点赞收藏哦!
Python经验分享
学好 Python 不论是用于就业还是做副业赚钱都不错,而且学好Python还能契合未来发展趋势——人工智能、机器学习、深度学习等。
小编是一名Python开发工程师,自己整理了一套最新的Python系统学习教程,包括从基础的python脚本到web开发、爬虫、数据分析、数据可视化、机器学习等。如果你也喜欢编程,想通过学习Python转行、做副业或者提升工作效率,这份【最新全套Python学习资料】 一定对你有用!
小编为对Python感兴趣的小伙伴准备了以下籽料 !
对于0基础小白入门:
如果你是零基础小白,想快速入门Python是可以考虑培训的!
- 学习时间相对较短,学习内容更全面更集中
- 可以找到适合自己的学习方案
包括:Python激活码+安装包、Python web开发,Python爬虫,Python数据分析,人工智能、机器学习、Python量化交易等学习教程。带你从零基础系统性的学好Python!
一、Python所有方向的学习路线
Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、学习软件
工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。
三、入门学习视频
我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。
四、实战案例
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
五、面试资料
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
最新全套【Python入门到进阶资料 & 实战源码 &安装工具】(安全链接,放心点击)
我已经上传至CSDN官方,如果需要可以扫描下方官方二维码免费获取【保证100%免费】
*今天的分享就到这里,喜欢且对你有所帮助的话,记得点赞关注哦~下回见 !