如何才能在计算机内存里有效地存储和访问那些对象集合呢?

  • 计算机内存是一系列存储位置。每一个存储位置都有一个与之关联的数字(很像索引),这个数字被称为内存的地址(address)。
  • 一个数据的存储,可以跨过若干连续的存储位置。
  • 要从内存中找出一个元素,我们需要一种方法来查找或者计算对象的起始地址
  • 当我们想要存储一组对象的时候,我们需要一些系统方法来确定集合中每个对象的位置。

假设一个集合里的所有对象尺寸都相同,也就是说它们都需要相同数量的字节来进行存储。这是同质(所有相同类型)集合的情况。存储这个集合的简单方法是分配一块足以容纳整个集合的单个连续存储区域。然后,就可以一个接一个地存储对象了。例如,假设一个整数值需要4字节(32位)的内存来存储,那么,100个整数的集合可以顺序存储到400字节的内存之中。假设这个整数集合从地址为1024的内存位置开始,也就是说,列表里索引为0处的数字是从地址1024开始的;索引1的数字的内存地址位于1028;索引2的数字的内存地址位于1032,以此类推。于是乎,对于第i个位置的元素,只需要通过公式[插图]就能够计算出它的地址。

我们刚刚描述的是一种被称为数组(array)的数据结构。
数组是用于存储集合的常用数据结构,许多编程语言都用数组作为基本的容器类型。
数组在内存里非常高效,而且基于我们刚才讨论过的内存地址索引计算公式,它还支持快速的随机访问(就是说我们可以直接“跳转”到我们想要的元素上)。然而,就数组而言,它们还是有些限制性的。其中一个问题是数组通常必须是同质的。通常不可能有同时包含整数和字符串的数组。为了能够使用内存地址索引计算公式,所有的元素都必须具有相同的尺寸

数组的另一个缺点是,在为其分配内存时需要确定数组的尺寸。在编程语言的语境中,数组通常都会被认为是静态的。当我们为100个元素分配一个数组的时候,底层的操作系统会给我们一个足以容纳该集合的内存区域。但是,数组周围的内存将会被分配给其他对象(甚至是其他正在运行的程序)。如果之后我们还想添加更多的元素,但是数组已经没法变大了,程序员可以通过这样的操作在某种程度上解决这个集合的这个限制:创建一个足够大的数组,来保持一块从理论上能够得到的最大集合的内存尺寸。然后通过了解这个数组实际使用了多少空间,程序员可以允许这个集合增长或缩小到合适的尺寸。但是,这样做会对数组的内存效率产生负面效应,因为程序员只能请求比实际需要更多的内存来保证工作。而且,很明显,如果集合的尺寸还是超出了预期的最大值,我们还是会遇到问题。

与数组相比,Python列表是异质(可以混合不同类型的对象)以及动态(可以按需增长或缩小)的。在底层,Python列表实际上还是使用数组来实现的。要知道,Python的变量存储都是对实际数据对象的引用。如果你不熟悉或不完全理解引用这个概念的话,请不要过于担心,我们将会在下一章里详细地讨论它们。这里的要点是,存储在Python列表数组的连续内存位置的元素,是实际数据对象的地址。而每一个内存地址的长度都是相同(在现代CPU上通常为32位或64位)的。要从列表中查找一个值,Python解释器首先会使用索引公式来查找对象的引用(地址)位置,然后使用这个引用来查找对象。因此,具有固定尺寸元素的数组可用于存储内存地址,然后用来查找任意尺寸的对象

很明显,Python列表也能够通过调用insert和append等方法来增长。在底层,Python会为列表分配一个固定尺寸的数组,并追踪这个固定尺寸作为最大值,并且还会追踪列表的当前尺寸。在尝试添加新元素时,一旦超出当前的最大尺寸,就必须分配足以存储所有元素的新的连续内存部分。然后将存储在旧数组中的引用复制到新的更大的数组里,最后释放用于存储旧列表的存储空间(返回给操作系统)。通过使用动态数组分配的能力,只要有足够的系统内存可以被用于保存新列表,Python列表就可以不断地增长。

效率分析

知道了Python列表是通过动态调整数组的尺寸来实现的,我们现在就可以分析各种列表操作的运行时效率了。分配新的较大数组是一项相对昂贵的操作,因此分配的新数组通常要大得多。分配更大的数组可防止在把大量额外的元素添加到数组之前,就又要去执行一次调整尺寸的操作。这也就意味着,把元素添加到Python列表的末尾,偶尔会需要Θ (n)的计算量(分配新数组并复制现有项):但大多数时候它都会是一个Θ (1)的操作。如果数组的尺寸在每次调整尺寸的时候都加倍的话,那么在执行n次添加到末尾(append)操作之后,才需要进行一次代价为Θ (n)的调整尺寸的操作。分摊到其他n个不需要调整尺寸操作的情况里,添加到末尾(append)操作的平均时间复杂度为Θ (1)。

Python列表还支持从现有列表中删除一个元素的方法。删除操作的方法和插入操作是相同的。如果我们删除位于位置4的元素,那么位置5和之后位置的所有元素必须向前移动一个位置。因此删除操作就像插入操作一样,是Θ (n)操作。删除一个元素时,我们不需要去更改列表的最大尺寸。因此,如果列表在短时间内变得非常大,然后变小并且在程序的其他时候都保持这种小得多的状态,分配来用于存储最大尺寸的内存将始终处于被占用的状态,而不会被释放。

总结

  • python列表基于数组实现
  • python动态扩容数组实现列表的可变长度
  • python 列表存储的是地址,因此可以解决数组不能存储异质对象的局限
  • python 列表可以类比java中的arraylist
  • python 列表操作的时间复杂度要从数组的本质去考虑

Python 列表实现原理相关推荐

  1. python列表实现原理_Python动态类型实现原理及过程解析

    在python中,我们使用变量时,并没有声明变量的存在和类型.类型是在运行过程中自动决定的. a = 3 python将会执行三步去完成上面这个请求. 1.创建一个对象代表3 2.创建一个变量a,如果 ...

  2. python列表生成式原理_三元表达式/和/或如何在Python中工作/真与假的性质/列表生成/生成器,and,or,执行,原理,True,False,本质,生成式...

    一看标题,看似是三个不相关的问题,实际上息息相关. 我们都知道,"C系语言(C\C++.C#.Java等)"都有一个共同的知识点:三目运算符,其主要作用还是为了简化选择结构语句.让 ...

  3. python列表的实现原理_Python列表对象实现原理

    Python 列表对象实现原理 Python 中的列表基于 PyListObject 实现,列表支持元 素的插入.删除.更新操作,因此 PyListObject 是一个变长 对象(列表的长度随着元素的 ...

  4. python list 实现原理,Python 列表(List)的底层实现原理分析

    Python 列表的数据结构是怎么样的? 列表实际上采用的就是数据结构中的顺序表,而且是一种采用分离式技术实现的动态顺序表 但这是不是Python的列表? 我的结论是顺序表是列表的一种实现方式. 书上 ...

  5. 微课系列(一):Python列表remove()方法工作原理

    技术要点: 1)在列表非尾部增加或删除元素时,该位置后面元素会向后移动或向前移动,保证元素之间没有缝隙,这样的话,这些元素的索引会发生变化. 2)remove()方法删除列表中指定值的首次出现,也就是 ...

  6. 深度解密 Python 列表的实现原理

    这是「进击的Coder」的第 751 篇技术分享 作者:古明地觉 来源:古明地觉的编程教室 " 阅读本文大概需要 13 分钟. " 楔子 最近有读者发了一条私信,希望我介绍一下 P ...

  7. python基础知识资料-学习Python列表的基础知识汇总

    千里之行,始于足下.要练成一双洞悉一切的眼睛,还是得先把基本功扎扎实实地学好.今天,本喵带大家仔细温习一下Python的列表.温故而知新,不亦说乎. 当然,温习的同时也要发散思考,因为有些看似无关紧要 ...

  8. Python 列表复制

    关于Python 列表的复制,有多种方法,常用的 有 赋值.切片.list.copy,copy.deepcopy等. 但是 实际用时 又有区别,不小心可能就用错了. 接下来 简单举例 说明一下 使用 ...

  9. python列表元素零的移动_python列表多行

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 这个列表推导式共有145列: memberdef_list = and std: ...

最新文章

  1. LRU算法确定最后使用时间的顺序-计数器
  2. 壁布接缝压条_墙布压条样板
  3. const深度总结(effective C++)
  4. mysql 按月统计 包括空月_mysql 按月统计但是有几个月没有数据,需要变成0
  5. ASP.Net中OnBeforeUnLoad事件中调用__doPostBack不起作用?
  6. jyputer notebook 、jypyter、IPython basics
  7. 设置linux文件系统密码,busybox 文件系统设置 登陆 login 密码 password shadow
  8. python与h5结合实例_使用h5py合并所有h5文件
  9. 疑似小米11系列旗舰跑分曝光:骁龙875性能突破天际
  10. mysql自动拉入黑名单_利用MySQL实现域名黑名单过滤10W记录1ms匹配
  11. Unity5.x 依赖关系打包 AssetBundle 研究
  12. 展讯DTS路径及编译
  13. 卧槽!AI 质检竟然还能这么玩???
  14. 基于32×32点阵LED模块的书写显示屏
  15. python qq群聊机器人_群聊太多?三步教你用 Python 自动监听转发群消息
  16. 三层交换机如何配置为网关
  17. 025_GPIO的读
  18. 服务器操作系统 份额,2019年6月全球桌面操作系统市场份额数据:Linux占比1.55%...
  19. 【Spring】详解Spring全家桶
  20. 求最小公倍数c语言最简公式,C语言求最小公倍数和最大公约数三种算法(经典)...

热门文章

  1. 解决OpenCV编译时./bin: error while loading shared libraries: libopencv_highgui.so.3.2: cannot open的问题
  2. 防火墙审计策略和应用场景介绍(USG6307E)
  3. python全栈开发网络_Python全栈开发:django网络框架(二)
  4. Arcgis10.2安装及LicensenManager10.2启动失败解决方法
  5. pycharm怎么做html网页_html下拉菜单怎么做
  6. python按位处理二进制文件_对如何在python shell中对16位二进制数执行按位运算感到困惑...
  7. java中获取链表的第一个节点,两个链表中的第一个公共节点(java)
  8. 软件有效期如何实现_足疗洗浴收银软件如何实现跨店管理?
  9. java引用队列_java的强引用、软引用、弱引用、幻象引用,引用队列总结
  10. @Controller