python list 底层实现的数据结构_Python数据结构大起底——list篇

python内置的多种数据结构为编程提供了相当的便利,灵活的使用python中的内置数据类型可以达到事半功倍的效果,本文是对Python一些常用数据类型的整理,并列举出来了一些使用技巧。

使用最多的数据结构 list

list内置了许多方法,常用的如:list.append(x)

list.insert(i,x)

list.remove(x)

list.pop(i)

list.index(x, start, end)

list.sort(key, reverse)

list.reverse()

list.copy()

...

上面的方法中,根据字面意思就能知道方法的作用,灵活使用这些方法,可以实现出来其他的数据结构。

使用list实现stack

stack是一个后进先出的数据结构,不理解stack的可以参看我的这篇博客,他的接口一般被这样定义:

// Stack 接口,java代码表示public Interface Stack{

// 添加一个元素 public void push(Item item);

// 移除最后添加的元素,并返回这个元素 public Item pop();

// 空监测 public isEmpty();

}

在python的list中,pop()方法依旧存在,使用不带参数的pop方法,就会从移除list最后一个元素,而push()方法则等价于list的append方法。所以可以直接把list当做stack来使用。

stack = []

stack.append('a') # stack = ['a']

stack.append('b') # stack = ['b']

last = stack.pop() # last='b', stack=['a']

如果你觉得这样做不是很安全,万一一不小心调用了别的方法,很容易破坏数据结构,那么你可以使用list自己实现一个Stack(虽然这看上去有点脱裤子放屁):

class Stack:

def __init__(self):

¦ self._stack = []

def is_empty(self):

return False if self.stack else True

def pop(self):

return self._stack.pop()

def push(self, item):

self._stack.append(item)

def __iter__(self):

for item in self._stack:

yield item

使用list实现queue

queue的特点是先进先出,不理解queue的可以参看我的这篇文章,queue的接口一般包含如下几种方法:

// Queue接口,java代码表示public Interface Queue{

// 入队操作,添加到最右(后) public void enqueue(Item);

//出队操作,移除最早入队的(最左边) public Item dequeue();

public isEmpty();

}

值得庆祝的是,当我们要使用queue的时候并不要自己去编写一个queque的结构,直接使用python collections模块里面的deque即可,当然你也可以尝试自己实现。

deque保留了list的append方法,但是有而外的添加了一个popleft方法,从而实现了dequeque的操作。

from collections import deque

queue = deque()

queue.append(1) # [1]

queue.append(2) # [1, 2]

queue.append(3) # [1, 2, 3]

first = queue.popleft() # first=1, queue=[2, 3]

list Comprehensions 列表推导

python官方文档列出了三中创建列表的方式,他们分别是迭代器,lambda和列表推导

# 使用迭代去

squares = []

for x in range(10):

squares.append(x**2)

# 使用lambda

squares = list(map(lambda x:x**2, range(10)))

# 使用列表推导

squares = [x**2 for x in range(10)]

列表推导式可以让代码变得更加简洁,解决2SUM问题,使用列表推导只需要一行代码即可暴力求解:

# 从1到100,两两组合,求所有合为105的组合

[(x, y) for x in range(1,101) y in range(1,101) if (x != y and x+y == 105)]

列表推导式还支持嵌套,如生成一个二维数组

# 生成一个5*5的二维数组

[[i for i in range(5)] for col in range(5) ]

del操作

list之所以能够把很多不同类型的数据放在一个集合里面,其他原因在于python的引用特性,所以对于列表内的任何一个元素都可以直接del。

a = [1, 2, 3, 4, 5]

del a[0] # 可以直接del

del a[2:4] # 也可以按照范围del,范围是左闭右开[2:4)

引用的陷阱

[[i for i in range(5)] for col in range(5) ]

这是上面用来创建二维数组的例子,有些比较聪明的人,可能会想到利用python的语言特性,与时代吗可能会这么写:

[[i for i in range(5)] * 5]

这看上去很简洁,并且两段代码输出的内容确实一毛一样的,但这并不称得上是聪明,简直愚蠢。事实上,当你尝试修改二维数组的任何一列的时候,每一列都会被改变。

a = [[i for i in range(5)] * 5]

# output a:

# [

# [1,2,3,4,5],

# [1,2,3,4,5],

# [1,2,3,4,5],

# [1,2,3,4,5],

# [1,2,3,4,5],

# ]

a[0][0] = 5

# output a:

# [

# [5,2,3,4,5],

# [5,2,3,4,5],

# [5,2,3,4,5],

# [5,2,3,4,5],

# [5,2,3,4,5],

# ]

出现上面巨大bug的原因就是,内存中事实上只创建了a[0],后面的几列由于使用的是*操作符,都没有创建新的内存空间,本质上他们是同一块内存块。

copy和deepcopy

同样的问题还会出现在数组拷贝的时候。

a = [[1,2,3], [4,5,6]]

b = a.copy()

a[0][0] = [9]

print(a, b)

上面的代码使用list的copy方法,把a复制了一份给b,按照字面意思理解,也就是说重新开辟了一块儿内存空间,并把a的内容copy进去,这样a和b就完全是两个独立的内存空间了。

但事实上上面的代码,修改了a[0][0]之后,b[0][0]紧跟着也变成了9.这就有点匪夷所思了。这是由于拷贝的深度有限,list默认的copy在一维数组使用并没有太大问题,但一旦数组内包含了其他深一层的引用,copy只会复制最上层,这样对于两块内存块来说,再往下一层,本质上还是使用了同一块内存块。所以就发生了上面匪夷所思的问题。

解决问题的办法是使用深拷贝,python 的list并没有实现deepcopy,但我们可以在copy模块中找到他。

import copy

a = [[1,2,3], [4,5,6]]

b = copy.deepcopy(a)

然后从最外层到最内层,完完全全的拷贝了a,a与b再也不会有哪一个元素共同同一块儿内存了。

总结

python对list的实现和功能的设计恰到好处,既不感到臃肿,又绝对够用,毕竟他是python数据结构的核心。在某些情况下你也可以选择不使用list,这个时候可以参见python的collections模块,寻找其他适合你的集合类型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/527319.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信wechat.class.php,laravel使用组件实现微信网页授权登入

laravel框架中的实现简单实现微信网页授权登入首先引入基于laravel的easywechat的组件,laravel版本5.8$ cd laravel$ composer require "overtrue/laravel-wechat:~5.0"然后呢因为下载过程会比较缓慢所以可以先根据官方提供的方式配置一下该组件的中间件根据官方提供…

linux 扩展挂载盘大小_Linux 添加挂载硬盘(包含挂载大于2T以上硬盘)

转自:http://blog.csdn.net/season_hangzhou/article/details/36423223由于事先规划问题或者业务需求量激增,总会出现机器硬盘空间不够用的情况所以常常需要新增硬盘,操作方法如下一、安装硬盘到物理机上。二、查看硬盘是否正确安装。使用“f…

oracle 存储过程打印语句,oracle学习之第一个存储过程:打印Hello World

--第一个存储过程:打印Hello World/*调用存储过程2种方式:1、exec sayhelloworld();2、beginsayhelloworld();sayhelloworld();end;/*/create or replace procedure sayhelloworld --假设这个存储过程存在就replace替换否则create创建,这里创…

oracle 运维入门,Oracle日常基本运维命令及基本体系结构

Oracle日常基本运维命令及基本体系结构发布人:中嘉和信发布时间:2020.05.11来源:运维派中嘉和信北京机房以康盛机房、亦庄国际机房、四季青机房为主,作为互联网数据中心集成服务领域的标杆企业,中嘉和信一直以客户需求…

qc成果报告范例_质量引领创新 扬子江勇夺医药行业QC“十五连冠”

近日,第40届全国医药行业QC小组成果发布交流会圆满落幕,扬子江药业集团勇夺QC一等奖总数“十五连冠”。会上,业界人士共享新成果、带来新思考、集聚新视野。扬子江人凭借高标准、高要求的精益求精的创新精神,在产品质量、技术、人…

php关联图片,PHP关联链接添加方法

PHP关联链接添加方法为了优化内链,我们需要将内容添加上关键链接,那内容如果添加关联链接呢,怎么添加呢?下面小编带大家一起来看看详细内容,希望对大家有所帮助!方法一:手动编辑添加方法二:使用程序在输出…

mysql数据表中取几列_MySQL实现表中取出随机数据

MySQL是开放源代码,MySQL因为其速度、可靠性和适应性而备受关注。大多数人都认为在不需要事务化处理的情况下,MySQL是管理内容最好的选择。 那么如何在MySQL实现表中取出随机数据呢?SELECT * FROM table_name ORDER BY rand() LIMIT 5;rand在…

获取php.ini配置信息,获得php所对应的配置文件(php.ini)信息

获得php所对应的配置文件(php.ini)信息[rootBIND9-master /usr/local/bin]# php --iniConfiguration File (php.ini) Path: /usr/local/etcLoaded Configuration File: /usr/local/Zend/etc/php.iniScan for additional .ini files in: /usr/local/etc/phpAdditional .…

android shpe 三角形_绘制三角形背景的android

I need to draw a background of layout as a triangle, like you can see in the picture.Ive found an example where they do something similar, but I dont know how to adapt it to my case. Here is the exampleCan anyone help me? Best.解决方案Here is an example o…

oracle 11g安装时设密码 database control,安装oracle 11g 保护Database Control时出错,Database Control已在非安全模式下启动...

错误解决:打开cmdC:\Users\lin>emctl status dbconsoleEnvironment variable ORACLE_UNQNAME not defined. Please set ORACLE_UNQNAME to database unique name.C:\Users\lin>C:\Users\lin>set oracle_sidorclC:\Users\lin>emca -config dbcontrol dbE…

python中argument函数_PythonStudy——函数的参数 Function argument

形参与实参# 参数介绍:# 函数为什么要有参数:因为内部的函数体需要外部的数据# 怎么定义函数的参数:在定义函数阶段,函数名后面()中来定义函数的参数# 怎么使用函数的参数:在函数体中用定义的参数名直接使用# 实参&…

matlab 分隔线,matlab字符分割方法

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼以下是我编的,您给看一下,往下我就不会了。。。。。希望您能帮帮我clear allclose alliimread(C:\Users\lenovo\Desktop\验证码.bmp)jrgb2gray(i)figure(1),imshow(i),title(原始彩色图像)figure,imshow(j),…

oracle fs1 2多少u,甲骨文FS1系列闪存的“大道至简”

近年来,存储技术中,闪存技术顶着“最高效挖掘数据能力”和“最小容量需求”的称号试图颠覆传统存储的技术架构和竞争格局。据IDC预测,全闪存存储阵列市场规模在2015年将增至12亿美元,而到2016年这一市场将增至16亿美元&#xff0c…

python boxplot orient_Python 可视化 | Seaborn5 分钟入门 (三)——boxplot 和 violinplot

微信公众号:「Python读财」如有问题或建议,请公众号留言Seaborn是基于matplotlib的Python可视化库。 它提供了一个高级界面来绘制有吸引力的统计图形。Seaborn其实是在matplotlib的基础上进行了更高级的API封装,从而使得作图更加容易&#xf…

kibana 更新 索引模式_升级 Kibana - Kibana 中文文档

IMPORTANT:在升级 Kibana 之前:请参考重要变更文档。在升级生产服务之前请先在测试环境测试升级。使用 Elasticsearch 的 snapshots 特性备份数据。除非存在备份数据,否则版本 不能向前回滚 。如果使用了自定义插件,检查其是否有兼容版本。从…

oracle裁员原因_Oracle大幅度裁员意味着什么?

近日,Oracle开始大幅度裁撤中国区研发中心(CDC),整个CDC一共1600人,被裁掉的将有900人,近六成的员工将面临失业。Oracle中国如此大动作裁员的原因究竟是什么呢?2018财年,甲骨文总营收为398.31亿美元&#x…

oracle计算1到一百偶数的和,Perl 打印在1..100内所有偶数和奇数

#!/usr/bin/perl -w#本程序用来打印#1-100的所有偶数#1-100的所有奇数#1-100里所有以1、2、7结尾的数for(my $i1;$i<100;$i){if (!($i % 2)){print "$i\t";}}print "\n";for(my $i1;$i<100;$i){if ($i % 2){print "$i\t";}}print "\n…

python微信集成_Python微信公众号后台开发005:集成智能聊天机器人​

​给公众号集成一个智能聊天机器人一、前述ChatterBot是一个基于机器学习的聊天机器人引擎&#xff0c;构建在python上&#xff0c;主要特点是可以自可以从已有的对话中进行学(jiyi)习(pipei)。二、具体1、安装是的&#xff0c;安装超级简单&#xff0c;用pip就可以啦pip insta…

django oracle 性能,4.利用Django在前端展示Oracle 状态趋势

利用Django在前端展示Oracle 状态趋势2017-12-15 Python 宅必备开发环境操作系统:CentOS 7.4Python版本 :3.6Django版本: 1.10.5操作系统用户:oms数据处理:pandas前端展示:highcharts通过上面我们已介绍了如何定时获取系统Oracle状态语句以及如何利用pandas处理成highcharts识别…

分段二次插值例题_分段三次插值

摘要用函数来表示变量间的数量关系广泛应用于各学科领域&#xff0c;但是在实际问题中&#xff0c;往往是通过实验、观测以及计算等方法&#xff0c;得到的是函数在一些点上的函数值。如何通过这些离散数据找到函数的一个满足精度要求且便于使用的近似表达式&#xff0c;是经常…