概述
内容包括
用途 | 推荐方式 |
---|---|
生成list | 一维使用[0]*n,二维采用[0]*n嵌套for-range的形式 |
list与set | 频繁的删除元素,如果不需要根据索引查看内容的话,使用set更节约时间 |
list生成效率
有时做leetcode题目时,存储结果需要提前生成固定大小的list,那么方式更快一些呢?以生成二维list为例
首先是[0]*n+for—range的方式
import time
start = time.time()
for i in range(1000):
temp = [[0]*1000 for _ in range(1000)]
end = time.time()
print(end - start)#5.878307104110718s
首先是for—range+for—range的方式
import time
start = time.time()
for i in range(1000):
temp = [[0 for _ in range(1000)] for _ in range(1000)]
end = time.time()
print(end - start)#30.824012517929077s
结论[0]*n+for—range更快,有人会想到使用[[0]*n]*n生成二维list,这样速度是最快的,但是实际上会出现如下问题,这五个子list其实都是同一个list,对其中一个更改会导致均发生更改,无法完成自己想要的操作。
>>> a = [[0]*5]*5
>>> a
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
>>> a[0][0] = 5
>>> a
[[5, 0, 0, 0, 0], [5, 0, 0, 0, 0], [5, 0, 0, 0, 0], [5, 0, 0, 0, 0], [5, 0, 0, 0, 0]]
list与set效率对比
首先list的底层实现是一个类数组结构,具体文章可以看这里
http://www.laurentluce.com/posts/python-list-implementation/
而set底层是一种hash表的结构,这就导致二者增删操作的差异性,set优于list,但是无法进行对于下标的索引
list增加操作
import time
temp = []
start = time.time()
for i in range(int(1e8)):
temp.append(i)
end = time.time()
print(end - start)#8.463991403579712s
set的增加操作
import time
temp = set()
start = time.time()
for i in range(int(1e8)):
temp.add(i)
end = time.time()
print(end - start)#10.350674152374268s
关于增加的操作,二者没有过大的差别,这是归功于list的提前扩大内容量的原理,见上面的链接
list的删除操作
import time
temp = [i for i in range(int(1e5))]
start = time.time()
for i in range(int(1e5)):
temp.remove(i)
end = time.time()
print(end - start)#0.9296932220458984s
set的删除操作
import time
temp = set([i for i in range(int(1e5))])
start = time.time()
for i in range(int(1e5)):
temp.remove(i)
end = time.time()
print(end - start)#0.010970592498779297s
可以看到是数量级的差异,这时因为remove在list操作中是O(n)复杂度的操作,而在set中是O(1)的复杂度
可能的疑惑
在使用for循环的时候,对于temp这种可迭代的对象有一个疑问for i in range(len(temp)):这种使用方式与提前计算出n=len(temp),而后使用for i in range(n)会不会更加优化,毕竟看起来前者每次循环都会计算一个len(temp)后判断是否应该继续循环(来源于c的想法)
下面进行测试
第一种方式
import time
temp = ["a"]*int(1e7)
start = time.time()
for i in range(len(temp)):
pass
end = time.time()
print(end - start)#0.30315184593200684s
第二种看似节约时间的方式
import time
temp = ["a"]*int(1e7)
n = len(temp)
start = time.time()
for i in range(n):
pass
end = time.time()
print(end - start)#0.3273622989654541s
忽略了计算机每次的误差,可以认为两种方式的耗时是相同的,可以认为在第一种方式中,仅仅在第一次循环中计算了len(temp)的值,而后便判断是否满足条件便可以了,当然在循环中改变迭代对象的大小一定会重新调用len(temp)的函数的
但当使用while的时候
第一种方式
import time
temp = ["a"]*int(1e8)
start = time.time()
i = 0
while i < len(temp):
i += 1
end = time.time()
print(end - start)#12.039517164230347s
第二种方式
import time
temp = ["a"]*int(1e8)
n = len(temp)
start = time.time()
i = 0
while i < n:
i += 1
end = time.time()
print(end - start)#7.073049068450928s
可以看出while循环每次判断都使用了len(temp)函数,说明使用for循环的时候对range(len(temp))进行了优化
最后
以上就是冷傲缘分为你收集整理的python一些操作的效率对比的全部内容,希望文章能够帮你解决python一些操作的效率对比所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复