点击上方蓝色小字 “小菜学编程” ,关注我们?

笔者经常在面试中与候选人探讨 Python 内置容器对象, list 作为最常用容器中的一员,肯定少不了它:

  • 你用过 list 对象吗?
  • list 对象都支持哪些操作?时间复杂度、空间复杂度分别是多少?
  • 试分析 appendinsert 这两个方法的时间复杂度?
  • 头部追加性能较差,如何解决?

list 对象的基本用法和技术原理,每个 Python 开发工程师都必须掌握,但不少候选人对此却只是一知半解。本节,我们一起查缺补漏,力求彻底掌握 list 对象,完美解答面试官针对 list 对象的灵魂之问。

基本用法

我们先来回顾一下 list 对象的基本操作:

# 新建一个列表>>> l = [1, 2, 3]>>> l[1, 2, 3]

# 向尾部追加元素,列表对象视情况自动扩容>>> l.append(4)>>> l[1, 2, 3, 4]

# 从尾部弹出元素,列表对象视情况自动缩容>>> l.pop()4>>> l[1, 2, 3]

# 向头部插入元素,该操作需要挪动后面的元素,谨慎使用!>>> l.insert(0, 4)>>> l[4, 1, 2, 3]

# 从头部弹出元素,该操作需要挪动后面的元素,谨慎使用!>>> l.pop(0)4>>> l[1, 2, 3]

# 查找元素第一次出现位置的下标>>> l.index(2)1

# 用一个可迭代对象扩展列表——元素逐一追加到尾部>>> l.extend([1, 2])>>> l[1, 2, 3, 1, 2]

# 计算元素出现的个数>>> l.count(1)2>>> l.count(3)1

# 将列表反转>>> l.reverse()>>> l[2, 1, 3, 2, 1]

# 将列表清空>>> l.clear()>>> l[]

一个合格的 Python 开发工程师,除了必须熟练掌握 list 对象的基本操作,还需要对每个操作的 实现原理 及对应的 时间复杂度 、 空间复杂度 有准确的认识。列表操作总体比较简单,但有个操作特别容易被误用:

  • insert 方法向头部追加元素时需要挪动整个列表,时间复杂度是  ,性能极差,需谨慎使用;
  • append 方法向尾部追加元素时,无需挪动任何元素,时间复杂度是  ;
  • pop 方法从头部弹出元素时也需要挪动整个列表,时间复杂度是  ,同样需谨慎使用;
  • pop 方法从尾部弹出元素时,无需挪动任何元素,时间复杂度是  ;

由此可见,对列表头部和尾部进行操作,性能有天壤之别。后续我们将一起探索 list 对象内部结构,从中寻找造成这种现象的原因。此外, list 对象还可根据元素个数 自动扩缩容 ,其中秘密也将一一揭晓。

内部结构

list 对象在 Python 内部,由 PyListObject 结构体表示,定义于头文件 Include/listobject.h 中:

typedef struct {    PyObject_VAR_HEAD    /* Vector of pointers to list elements.  list[0] is ob_item[0], etc. */    PyObject **ob_item;

    /* ob_item contains space for 'allocated' elements.  The number     * currently in use is ob_size.     * Invariants:     *     0 <= ob_size <= allocated     *     len(list) == ob_size     *     ob_item == NULL implies ob_size == allocated == 0     * list.sort() temporarily sets allocated to -1 to detect mutations.     *     * Items must normally not be NULL, except during construction when     * the list is not yet visible outside the function that builds it.     */    Py_ssize_t allocated;} PyListObject;

毫无疑问, list 对象是一种 变长对象 ,因此包含变长对象公共头部。除了公共头部, list 内部维护了一个动态数组,而数组则依次保存元素对象的指针:

  • ob_item ,指向动态数组的指针,动态数组保存元素对象的指针;
  • allocated ,动态数组长度,即列表 容量 ;
  • ob_size ,动态数组当前保存元素个数,即列表 长度 ;

尾部操作

在列表对象尾部增删元素,可快速完成,无须挪动其他元素。

假设列表元素 l 内部数组长度为 5 ,以及保存 3 个元素,分别是:1 、 2 、 3 。当我们调用 append 方法向尾部追加元素时,由于内部数组还有未用满,只需将新元素保存于数组下一可用位置并更新 ob_size 字段:


因此,大多数情况下, append 方法性能都足够好,时间复杂度是  。

list 对象除了尾部操作外,还有 动态扩容头部操作元素 以及 浅拷贝 等常用方法,这些你又掌握了多少呢?点击 “

?  原创不易,求赞,求在看

list对象_list对象,容量自适应的数组式容器相关推荐

  1. vue根据索引删除数组中的一个对象_Vue实现动态添加或者删除对象和对象数组的操作方法...

    添加核心代码如下: this.data.push({ type: [{ value: '选项1', label: 'in' }, { value: '选项3', label: 'out' }], va ...

  2. javascript 学习之 数组式的对象

    javascript数组的特殊之处在于它的length属性: 1,当有元素被添加或删除时,它是自动更新的. 2,通过设置这个属性的值就可以扩展或者截短它. javascript数组也是实例数组,各种方 ...

  3. java object 转byte_Java将对象Object转换成Byte字节数组

    Java将对象Object转换成Byte字节数组的代码如下: /** * @from www.ityuan.com * @Description: Java将对象Object转换成Byte字节数组 * ...

  4. vue 对象中数组中对象某个属性更改_vue之监听对象、对象数组的改变

    vue之监听对象的改变 一.对象监听 1. 深度监听 change name:'test', data () {return{ user: { id:1, name: '李四', age: 14, s ...

  5. json数组对象和对象数组

    一.Json的简单介绍 从结构上看,所有的数据最终都可以分成三种类型: 第一种类型是scalar(标量),也就是一个单独的string(字符串)或数字(numbers),比如"北京" ...

  6. java网课|匿名对象Random对象数组

    P119 匿名对象的使用 什么是匿名对象? new 类名称(): 没有左边的名字和= //匿名对象 new Person(); 2个new 2个对象 ==>调用showName时不会显示赵又廷! ...

  7. Java 定义一个抽象类—水果,其中包括getWeight()方法,创建若干水果对象存放在一个水果类型的数组中,输出数组中所有水果的类型、重量。

    Java 定义一个抽象类-水果 其中包括getWeight()方法,编写程序分别创建苹果.桃子.橘子3个类,创建若干水果对象存放在一个水果类型的数组中,输出数组中所有水果的类型.重量. 抽象类Frui ...

  8. json对象(json对象和json数组)

    使用Struts2的json插件转换对象的配置问题Action 你好,你可以跟客服去咨询一下. java如果将一个文件变成json对象我有一个文件,需要通过ja google搜索gson 灰常好用的工 ...

  9. JavaScript求数组中每个元素的个数,如数组str = [1,2,3,2,4,1,2]中元素2的个数为2。要求:使用对象知识来实现,输出结果为对象,对象包含数组元素和个数值。

    求数组中每个元素的个数,如数组str = [1,2,3,2,4,1,2]中元素2的个数为2. 要求:使用对象知识来实现,输出结果为对象,对象包含数组元素和个数值. <script>var ...

最新文章

  1. 抽象类,虚方法,接口
  2. 读书笔记-单元测试艺术(二)-单元测试框架
  3. char* 大小_SQL Server中char, nchar, varchar和nvarchar数据类型有何区别
  4. superset数据集birth_names的负时间戳处理
  5. C#编程中的66个好习惯,你有多少个?(转)
  6. 【云栖号案例 | 教育与科研机构】红岭创投上云 成功顺应全球电子商务发展趋势
  7. Mono for Unreal Engine发布,C#进入虚幻引擎(Unreal Engine)
  8. K-means 聚类算法的图像区域分割
  9. 虚幻引擎编程基础(二)
  10. qemu-guest-agent调研
  11. 牛顿广义二项式定理-母函数
  12. H3C WA4320H-ACN 无线AP改成12V DC供电
  13. 2019吉大软件C++课设——模拟即时通信系统
  14. TryHackMe-Gatekeeper
  15. 分布式异步任务神器-Celery
  16. 【视频】IoT 物联网平台实例规格选型详解
  17. Webmail邮件***实战技术总结
  18. HDU 5528 狄利克雷卷积
  19. sqrt函数实现(神奇的算法)
  20. Java向pdf模板中写入数据并在模板之后添加新的表格内容

热门文章

  1. Linux网络包接收过程的监控与调优
  2. 复杂系统如何在不停机升级同时保持稳定?你必须考虑以下几个点...
  3. 浅谈 UC 国际信息流推荐
  4. 一文读懂云计算、边缘计算、移动边缘计算和自动驾驶的前世今生!
  5. 大数据开发源码视频今日免费送!
  6. OpenCV车牌/数字识别
  7. RK3399 Ubuntu修改任务栏为自动隐藏和修改桌面背景
  8. html es表达式传参,ES2015 正则表达式新增特性
  9. c语言实现指定路径文件读取_C语言实现文件复制功能(包括文本文件和二进制文件)...
  10. 计算机书籍-Python机器学习算法大全