【Python性能优化】list、array与set

embedded/2024/10/11 13:26:34/

list、array与set

  • 详述
  • 测试代码

 
 
 
 
 
 
 
 

详述


本文对比 list 与 set 在插入和取值时的性能差异,以提供一条什么时候该选择什么数据类型的建议。先上结果:

array 与 list 的不同:

  • 内存方面
    • array 是 C array 的包装,它直接存储数据,占用的内存大小 = 元素个数 * 元素类型
    • list 是 Python Object,其中存储的每个数据都会被包装成 Python Object,所以内存占用大的多
  • 数据类型方面
    • array 只能存储相同数据类型
    • list 可以存储不同数据类型
  • 操作时间
    • list 因为存储的就是 PyObject,所以进行各类处理不需要频繁的进行数据转换
    • array 存储原始的 C 数据,所以和其他 Python 数据进行操作时,每次都要进行类型转换

 
选择 list 的场景

  1. 需要数据是有序的
  2. 需要存储可变变量(列表、字典)的
  3. 数据中可能会有重复的

 
选择 set 的场景

  1. 当需要频繁判断数据存在性,时间复杂度为 O(1),list 和 array 均为 O(N),但是 array 比 list 慢的多,因为每次判断都要对 array 中的元素进行 PyObject 和原始数据类型的转换。而 set 的查询这么快,其本质是在 Python 内部,set 是使用 hash table 来构建的
  2. 数据是无序的
  3. 数据是不可变变量的
  4. 数据没有重复的
  5. 数据是不可变变量的

 
选择 array 的场景

  1. 需要更节省内存

 

测试结果

结果总结(速度):

  1. 插入大量数据 set > list >> array
  2. 判断存在性 set >>>>>>>>>>>>>> list >> array
  3. 弹出第一个值 array > list
  4. 弹出最后一个值 set > array > list
  5. 在首部插入数据 array >> list
  6. 在尾部插入数据 array ≈ list
  7. 追加数据(append 和 add)list > array > set

 
注意:上述总结中仅涉及对容器自身的操作,若在这些操作之外还有额外操作,主要重点注意 array中的数据转换为 PyObject 的性能开销,除非是数据量特别大,内存需要谨慎分配的场景,其他场景均建议使用 list 而非 array

在这里插入图片描述

 

1、插入 100 万数据的速度比

在这里插入图片描述

 

2、判断存在性,判断的第一个值就存在

在这里插入图片描述

 

3、判断存在性,判断的最后一个值才存在

在这里插入图片描述

 

4、弹出第一个值

在这里插入图片描述

 

5、弹出最后一个值

在这里插入图片描述

 

6、在首部插入数据

在这里插入图片描述

 

7、在尾部插入数据

在这里插入图片描述

 

7、追加数据

在这里插入图片描述

 
 
 
 
 
 
 
 

测试代码


python">from array import array
from timeit import timeitnumber = 100l = list()
t = timeit("for i in range(100_0000): l.append(i)", number=number, globals=globals())
print(f"[List] List append time: {t:.20f}")a = array("I")
t = timeit("for i in range(100_0000): a.append(i)", number=number, globals=globals())
print(f"[Array] Array append time: {t:.20f}")_s = set()
t = timeit("for i in range(100_0000): _s.add(i)", number=number, globals=globals())
print(f"[Set] Set append time: {t:.20f}")t = timeit("1 in l", number=number, globals=globals())
print(f"[List] First element in list: {t= :.20f}")t = timeit("1 in a", number=number, globals=globals())
print(f"[Array] First element in array: {t= :.20f}")t = timeit("1 in _s", number=number, globals=globals())
print(f"[Set] First element in set: {t= :.20f}")t = timeit("99_9999 in l", number=number, globals=globals())
print(f"[List] Last element in list: {t= :.20f}")t = timeit("99_9999 in a", number=number, globals=globals())
print(f"[Array] Last element in array: {t= :.20f}")t = timeit("99_9999 in _s", number=number, globals=globals())
print(f"[Set] Last element in set: {t= :.20f}")t = timeit("l.pop(0)", number=number, globals=globals())
print(f"[List] List pop 0: {t= :.20f}")t = timeit("a.pop(0)", number=number, globals=globals())
print(f"[Array] Array pop 0: {t= :.20f}")t = timeit("l.pop(-1)", number=number, globals=globals())
print(f"[List] List pop -1: {t= :.20f}")t = timeit("a.pop(-1)", number=number, globals=globals())
print(f"[Array] Array pop -1: {t= :.20f}")t = timeit("_s.pop()", number=number, globals=globals())
print(f"[Set] Set pop random: {t= :.20f}")t = timeit("l.insert(0, 0)", number=number, globals=globals())
print(f"[List] List insert first: {t= :.20f}")t = timeit("a.insert(0, 0)", number=number, globals=globals())
print(f"[Array] Array insert first: {t= :.20f}")t = timeit("l.insert(-1, 0)", number=number, globals=globals())
print(f"[List] List insert last: {t= :.20f}")t = timeit("a.insert(-1, 0)", number=number, globals=globals())
print(f"[Array] Array insert last: {t= :.20f}")t = timeit("l.append(0)", number=number, globals=globals())
print(f"[List] List append: {t= :.20f}")t = timeit("a.append(0)", number=number, globals=globals())
print(f"[Array] Array append: {t= :.20f}")t = timeit("_s.add(0)", number=number, globals=globals())
print(f"[Set] Set append: {t= :.20f}")

http://www.ppmy.cn/embedded/21644.html

相关文章

三个目前主流的计算机视觉软件

计算机视觉是人工智能的一个重要分支,它涉及到使计算机能够理解和解释图像和视频数据。近年来,计算机视觉领域取得了显著的进展,尤其是在深度学习的帮助下。尽管如此,将计算机视觉的能力直接与人类的视觉能力进行比较并不完全准确…

uniapp h5文件流下载pdf文件

今天遇到一个需求就是后端返回一个文件流,前端需要用户点击以后下载,那么怎么去做呢 请看下面代码 DownLoadDoc() {let url doc/api/downloadDocFulltext?id this.id //接口路径uni.request({url:uni.getStorageSync(baseUrl)url, //域名拼接response…

旅游网站制作流程

旅游网站制作流程是一个较复杂的过程,因为它需要结合市场调研、用户需求、内容构建、技术开发等多个方面。在这篇文章中,我将简单介绍一下旅游网站的制作流程,大致分为以下步骤。 第一步:市场调研 在制作旅游网站前,我…

ACE框架学习3

ACE Acceptor-Connector框架 该框架实现 Acceptor-Connector 模式,该模式解除了“网络化应用中的协作对端服务的连接和初始化”与“连接和初始化之后它们所执行的处理”的耦合。Acceptor-Connector 框架允许成用独立于它们所提供的服务来配置其连接布局的关键属性。…

Web前端一套全部清晰 ① 学习路线

一切都会好的,我一直相信 —— 24.4.25 基础入门:HTML5CSS3移动web技术进阶: JavaScript全套(js基础Web APIsjs进阶) ——> 《框架前置课》AJAX-Node.js-Webpack-GitVUE开发: 框架前置课Node.js&es6 ——> Vue2Vue3全套 ——> iHRM人力资源后台管理项 …

ctfshow-nodejs

web334 打开题目是一个登陆界面 下载题目中的附件,发现里面有用户名和密码 但还找到代码中有toUpperCase()函数为转为大写 因此用户名为ctfshow,密码为123456 输入即可得到flag web335 打开题目 发现只有一句话,查看源码 里面暗示有get…

【CLion】clion无法加载或找不到cmakekists文件

一、问题表象 最近工作中,在git pull远程仓库最新版本程序后,平时打开CLion自动加载的工程CMakeLists文件突然失效(显示找不到可编译的文件),无法debug程序。 二、原因分析 基于平时的编码经验和之前git pull也出现…

Cranck-Nicolson隐式方法解线性双曲型方程

Cranck-Nicolson隐式方法解线性双曲型方程 Cranck-Nicolson方法在抛物型方程里面比较常用,双曲型方程例子不多,该方法是二阶精度,无条件稳定,然而,数值震荡比较明显,特别是时间演化比较大以及courant数比较…