您好,我是码农飞哥,感谢您浏览本文,欢送一键三连哦
本文分十个章节介绍数据类型中的列表(list)和元组(tuple),从应用说到底层实现,包您称心
干货满满,倡议珍藏,须要用到时常看看。 小伙伴们如有问题及须要,欢送踊跃留言哦~ ~ ~。

一浅: 列表(list)的介绍

列表作为Python序列类型中的一种,其也是用于存储多个元素的一块内存空间,这些元素依照肯定的顺序排列。其数据结构是:

[element1, element2, element3, ..., elementn]

element1~elementn示意列表中的元素,元素的数据格式没有限度,只有是Python反对的数据格式都能够往里面方。同时因为列表反对主动扩容,所以它可变序列,即能够动静的批改列表,即能够批改,新增,删除列表元素。看个爽图吧!

二浅:列表的操作

首先介绍的是对列表的操作:包含列表的创立,列表的删除等!其中创立一个列表的形式有两种:
第一种形式:
通过[]包裹列表中的元素,每个元素之间通过逗号,宰割。元素类型不限并且同一列表中的每个元素的类型能够不雷同,然而不倡议这样做,因为如果每个元素的数据类型都不同的话则十分不不便对列表进行遍历解析。所以倡议一个列表只存同一种类型的元素

   list=[element1, element2, element3, ..., elementn]

例如:test_list = ['测试', 2, ['码农飞哥', '小伟'], (12, 23)]
PS: 空列表的定义是list=[]
第二种形式:
通过list(iterable)函数来创立列表,list函数是Python内置的函数。该函数传入的参数必须是可迭代的序列,比方字符串,列表,元组等等,如果iterable传入为空,则会创立一个空的列表。iterable不能只传一个数字。

classmates1 = list('码农飞哥')print(classmates1)

生成的列表是:['码', '农', '飞', '哥']

三浅:向列表中新增元素

向列表中新增元素的办法有四种,别离是:
第一种: 应用+运算符将多个列表连接起来。相当于在第一个列表的开端增加上另一个列表。其语法格局是listname1+listname2

name_list = ['码农飞哥', '小伟', '小小伟']name_list2 = ['python', 'java']print(name_list + name_list2)

输入后果是:['码农飞哥', '小伟', '小小伟', 'python', 'java'],能够看出将name_list2中的每个元素都增加到了name_list的开端。
第二种:应用append()办法增加元素
append()办法用于向列表开端增加元素,其语法格局是:listname.append(p_object)其中listname示意要增加元素的列表,p_object示意要增加到列表开端的元素,能够是字符串,数字,也能够是一个序列。举个栗子:

name_list.append('Adam')print(name_list)name_list.append(['test', 'test1'])print(name_list)

运行后果是:

['码农飞哥', '小伟', '小小伟', 'Adam']['码农飞哥', '小伟', '小小伟', 'Adam', ['test', 'test1']]

能够看出待增加的元素都胜利的增加到了原列表的开端处。并且当增加的元素是一个序列时,则会将该序列当成一个整体。
第三种:应用extend()办法
extend()办法跟append()办法的用法雷同,同样是向列表开端增加元素。元素的类型只须要Python反对的数据类型即可。不过与append()办法不同的是,当增加的元素是序列时,extend()办法不会将列表当成一个整体,而是将每个元素增加到列表开端。还是下面的那个例子:

name_list = ['码农飞哥', '小伟', '小小伟']name_list.extend('Adam')print(name_list)name_list.extend(['test', 'test1'])print(name_list)

运行后果是:

['码农飞哥', '小伟', '小小伟', 'A', 'd', 'a', 'm']['码农飞哥', '小伟', '小小伟', 'A', 'd', 'a', 'm', 'test', 'test1']

从后果看出,当增加字符串时会将字符串中的每个字符作为一个元素增加到列表的开端处,当增加的列表时会将列表中的每个元素增加到开端处。
第四种:应用insert()办法
后面介绍的几种插入方法,都只能向列表的开端处插入元素,如果想在列表指定地位插入元素则无能为力。insert()办法正式用于解决这种问题而来的。其语法结构是listname.insert(index, p_object) 其中index示意指定地位的索引值,insert()会将p_object插入到listname列表第index个元素的地位。与append()办法雷同的是,如果待增加的元素的是序列,则insert()会将该序列当成一个整体插入到列表的指定地位处。举个栗子:

name_list = ['码农飞哥', '小伟', '小小伟']name_list.insert(1, 'Jack')print(name_list)name_list.insert(2, ['test', 'test1'])print(name_list)

运行后果是:

['码农飞哥', 'Jack', '小伟', '小小伟']['码农飞哥', 'Jack', ['test', 'test1'], '小伟', '小小伟']

四浅:批改列表中的元素

说完了列表中元素新增的办法,接着让咱们来看看批改列表中的元素相干的办法。批改列表元素的办法有两种:
第一种:批改单个元素:
批改单个元素的办法就是对某个索引上的元素进行从新赋值。其语法结构是:listname[index]=newValue,就是将列表listname中索引值为index地位上的元素替换成newValue。
举个栗子:

name_list = ['码农飞哥', '小伟', '小小伟']name_list[1] = 'Sarah'print(name_list)

运行后果:['码农飞哥', 'Sarah', '小小伟'] 从后果能够看出索引为1处的元素值被胜利批改成了Sarch。
第二种:通过切片语法批改一组元素
通过切片语法能够批改一组元素,其语法结构是:listname[start:end:step],其中,listname示意列表名称,start示意起始地位,end示意完结地位(不包含),step示意步长,如果不指定步长,Python就不要求新赋值的元素个数与原来的元素个数雷同,这意味着,该操作能够为列表增加元素,也能够为列表删除元素。举个栗子:

name_list = ['码农飞哥', '小伟', '小小伟']name_list[0:1] = ['飞哥', '牛逼']print(name_list)

运行后果是:['飞哥', '牛逼', '小伟', '小小伟'] ,从后果能够看出将原列表中索引为0处的元素值曾经被替换为飞哥,并且插入了牛逼 这个元素。

五浅:删除列表中的元素

删除列表中元素的办法共有四种。
第一种:依据索引值删除元素的del关键字
依据索引值删除元素的del关键字有两种模式,一种是删除单个元素,del listname[index],一种是依据切片删除多个元素del listname[start : end],其中,listname示意列表名称,start示意起始索引,end示意完结索引,del会删除从索引start到end之间的元素,然而不包含end地位的元素。还是举个栗子:

name_list = ['码农飞哥', '小伟', '小小伟', '超人']name_list2 = name_listprint('原始的name_list={0}'.format(name_list))print('原始的name_list2={0}'.format(name_list2))# 删除索引0到2之间的元素,即删除索引0和索引1两个地位的元素del name_list[0:2]print('应用del删除元素后name_list={0}'.format(name_list))print('应用del删除元素后name_list2={0}'.format(name_list2))del name_listprint('应用del删除列表后name_list2={0}'.format(name_list2))

运行后果是:

原始的name_list=['码农飞哥', '小伟', '小小伟', '超人']原始的name_list2=['码农飞哥', '小伟', '小小伟', '超人']应用del删除元素后name_list=['小小伟', '超人']应用del删除元素后name_list2=['小小伟', '超人']应用del删除列表后name_list2=['小小伟', '超人']

能够看出用del删除列表元素时是实在的删除了内存数据的,然而用del删除列表时,则只是删除了变量,name_list2所指向的内存数据还是存在的。
第二种:依据索引值删除元素的pop()办法
依据索引值删除元素的pop()办法的语法结构是:listname.pop(index),其中,listname示意列表名称,index示意索引值,如果不写index参数,默认会删除列表中最初一个元素,相似于数据结构中的出栈操作。举个例子:

name_list = ['码农飞哥', '小伟', '小小伟', '超人']# 删除list开端的元素name_list.pop()print(name_list)# 删除指定地位的元素,用pop(i)办法,其中i是索引地位name_list.pop(1)print(name_list)

运行后果是:

['码农飞哥', '小伟', '小小伟']['码农飞哥', '小小伟']

第三种:依据元素值进行删除的remove()办法
依据元素值进行删除的remove()办法,其语法结构是:listname.remove(object),其中listname示意列表的名称,object示意待删除的元素名称。须要留神的是:如果元素在列表中不存在则会报ValueError的谬误。举个栗子:

name_list = ['码农飞哥', '小伟', '小小伟', '超人']name_list.remove('小小伟')print(name_list)

运行后果是:['码农飞哥', '小伟', '超人']
第四种:删除列表中的所有元素clear()办法
通过clear()办法能够删除掉列表中的所有元素,其语法结构是:listname.clear(),其中listname示意列表的名称。还是举个栗子吧:

name_list = ['码农飞哥', '小伟', '小小伟', '超人']name_list.clear()print(name_list)

运行后果是:[],能够看出列表中元素被全副清空了。

六浅:列表中元素的查找以及拜访

说完了第五浅列表元素的删除,略感疲乏。接着进行第六浅吧!看看列表中元素的查找以及拜访。看完这个之后,列表相干的内容也就告一段落了。

拜访列表中的元素

拜访列表中的元素有两种形式,别离是通过索引定位拜访单个元素,通过切片拜访多个元素。
第一种:通过索引定位拜访单个元素,其语法结构是:listname[index] ,其中listname示意列表的名字,index示意要查找元素的索引值。
第二种:通过切片的形式拜访多个元素,其语法结构是:listname[start:end:step]。其中,listname示意列表的名字,start示意开始索引,end示意完结索引(不包含end地位),step示意步长。同样是举个栗子:

list = ['码农飞哥', '小伟', '小小伟',123]print(list[0])  # 输入列表的第一个元素print(list[1:3])  # 输入第二个至第三个元素print(list[2:])  # 输入从第三个开始至列表开端的所有元素

运行后果是:

码农飞哥['小伟', '小小伟']['小小伟', 123]

查找某个元素在列表中呈现的地位 index()

indext()办法用来查找某个元素在列表中呈现的地位(也就是索引),如果该元素在列表中不存在,则会报ValueError谬误。其语法结构是:listname.index(object, start, end) 其中listname示意列表的名字,object示意要查找的元素,start示意起始索引,end示意完结索引(不包含)。

name_list = ['码农飞哥', '小伟', '小小伟', '超人']print(name_list.index('小伟', 0, 2))

运行后果是:1

七浅:列表应用技巧及注意事项

此处留一个空白,欢送小伙伴留言通知我,先看个图放松下吧!!

图片看完之后是不是感觉好多了,那就让咱们接着来学习吧。

Python新增元素中各个办法的区别

后面介绍了应用+运算符,应用append办法,应用extend办法都能够新增元素,那么他们到底有啥区别呢?还是举例说明吧;

name_list = ['码农飞哥', '小伟', '小小伟', '超人']name_list2 = ['牛魔王']name_list3 = name_list + name_list2print("原始的name_list的值={0};内存地址={1}".format(name_list, id(name_list)))print("应用+运算符后name_list3的值={0};内存地址={1}".format(name_list3, id(name_list3)))print("应用+运算符后name_list的值{0};内存地址={1}".format(name_list, id(name_list)))name_list4 = name_list.append('牛魔王')print('应用append办法后name_list4的值={0};内存地址={1}'.format(name_list4, id(name_list4)))print("应用append办法后name_list的值{0};内存地址={1}".format(name_list, id(name_list)))name_list5 = name_list.extend('牛魔王')print('应用extend办法后name_list5的值={0};内存地址={1}'.format(name_list4, id(name_list4)))print("应用extend办法后name_list的值{0};内存地址={1}".format(name_list, id(name_list)))

运行后果是:

原始的name_list的值=['码农飞哥', '小伟', '小小伟', '超人'];内存地址=2069467533448应用+运算符后name_list3的值=['码农飞哥', '小伟', '小小伟', '超人', '牛魔王'];内存地址=2069467533896应用+运算符后name_list的值['码农飞哥', '小伟', '小小伟', '超人'];内存地址=2069467533448应用append办法后name_list4的值=None;内存地址=2012521616应用append办法后name_list的值['码农飞哥', '小伟', '小小伟', '超人', '牛魔王'];内存地址=2069467533448应用extend办法后name_list5的值=None;内存地址=2012521616应用extend办法后name_list的值['码农飞哥', '小伟', '小小伟', '超人', '牛魔王', '牛', '魔', '王'];内存地址=2069467533448

从运行后果能够看出如下几点:

  1. 应用+运算符是创立一个新的列表,新列表的地址与原列表的地址不雷同,并且原始列表的内容不会扭转。
  2. append办法和extend办法都是批改原始列表的内容,并且都没有返回值,所以两者都不能应用链式表达式。
  3. 当待增加的元素是列表时,append办法会将列表当成一个整体,而extend不会。

八浅:元组(tuple)的介绍

说完了列表,接着让咱们来看看另外一个重要的序列--元组(tuple),和列表相似,元组也是由一系列按特定书序排序的元素组成,与列表最重要的区别是,元组属于不可变序列,即元组一旦被创立,它的元素就不可更改了。

元组的创立形式

第一种:应用()间接创立
应用()创立元组的语法结构是tuplename=(element1,element2,....,elementn),其中tuplename示意元组的变量名,element1~elementn示意元组中的元素。小括号不是必须的,只有将元素用逗号分隔,Python就会将其视为元组。还是举个栗子:

#创立元组tuple_name = ('码农飞哥', '小伟', '小小伟', '超人')print(tuple_name)#去掉小括号创立元组tuple2 = '码农飞哥', '小伟', '小小伟', '超人'print(type(tuple2))

运行后果是:

('码农飞哥', '小伟', '小小伟', '超人')<class 'tuple'>

第二种:应用tuple()函数创立
与列表相似的,咱们能够通过tuple(iterable)函数来创立元组,如果iterable传入为空,则创立一个空的元组,iterable 参数必须是可迭代的序列,比方字符串,列表,元组等。同样的iterable不能传入一个数字。举个栗子:

name_list = ['码农飞哥', '小伟', '小小伟', '超人']print(tuple(name_list))print(tuple('码农飞哥'))

运行后果是:

('码农飞哥', '小伟', '小小伟', '超人')('码', '农', '飞', '哥')

因为元组是不可变序列,所以没有批改元素相干的办法,只能对元组中的元素进行查看。查看元素的形式也与列表相似,共两种形式:
第一种:通过索引(index)拜访元组中的元素,其语法结构是tuplename[index]
第二种:通过切片的形式拜访,其语法结构是:tuplename[start:end:step]
相干参数的形容在此不再赘述了。仍然是举例说明:

tuple_name = ('码农飞哥', '小伟', '小小伟', '超人')# 获取索引为1的元素值print(tuple_name[1])#获取索引为1到索引为2之间的元素值,不包含索引2自身print(tuple_name[0:2])

运行后果是:

小伟('码农飞哥', '小伟')

元组中的元素不能批改,不过能够通过 + 来生成一个新的元组。

九浅:元组和列表的区别

说完了后面八浅之后,也有点累了。接着说下元组和列表的区别吧。为啥Python要另外设置元组这样一个数据结构呢?元组的性能列表不是都能够满足么?所以,这一浅次要是介绍元组的长处,存在即正当,哈哈哈哈。
区别:

  1. 元素是否能够批改?
    列表中的元素能够批改,而元组中的元素不能批改。如果强行批改元组中的元素,你会失去如下谬误:
TypeError: 'tuple' object does not support item assignment
  1. 存储同样数据所占空间
    上面展现初始化一个空列表和一个空元组所占的字节数
>>> listdemo = []>>> listdemo.__sizeof__()40>>> tupleDemo = ()>>> tupleDemo.__sizeof__()24

能够看出元组比列表少占用16个字节,这是因为列表是动静的,它须要存储指针来指向对应的元素(占用8个字节),另外,因为列表中的元素可变,所以须要额定存储曾经调配的长度大小(占用8个字节)。然而对于元组,状况就不同了,元组长度的大小固定,其存储元素不可变,所以存储空间也是固定的。总体来说,元组的存储性能要因为列表,存储同样数据所占用空间更小。

  1. 初始化同样数据所需工夫
    大家想一想初始化同样数据的元组和列表,哪个的速度更快呢?是元组还是列表呢?置信大部分人都会抉择元组,那么元组到底快多少呢?上面就用一个例子阐明一下:同样是初始化元素为1,2,3,4两个序列。
(python-demo)  root$ python3 -m timeit 'x=(1,2,3,4)'10000000 loops, best of 3: 0.029 usec per loop(python-demo)  root$ python3 -m timeit 'x=[1,2,3,4]'10000000 loops, best of 3: 0.165 usec per loop

初始化元组花了0.029秒,初始化话列表花了0.165 秒,所以,能够得出的论断是初始化一个雷同元素的列表和元组别离所需的工夫,元组的初始化速度要比列表快5倍多。

小结

元组有如下长处:元组比列表的拜访和处理速度更快,存储雷同内容所需空间更小。

一深:列表和元组的底层实现

九浅曾经实现了,最初就来一次更深刻的交换吧。知其然更要知其所以然。话不多说,上面就间接从源码层面来看看列表和元组的底层实现。
首先来剖析列表(list),它的具体构造如下所示:

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;

PS:列表实现的源码文件是 listobject.h 和 listobject.c。
list 实质上是一个长度可变的间断数组。其中ob_item是一个指针列表,外面的每个指针都指向列表中的元素,而allocated则用于存储该列表目前被调配的空间大小。
须要留神的是,allocated和列表的理论空间大小不同,列表理论空间大小是指len(list)返回的后果,即下面正文中的ob_size,示意该列表理论存储了多少个元素,而理论状况是,为了优化存储构造,防止每次减少元素都要从新分配内存,列表预调配的空间allocated往往大于ob_size。他们的关系是0 <= ob_size <= allocated
接下来在剖析元组,如下所示为Python3.7 tuple元组的具体构造:

typedef struct {    PyObject_VAR_HEAD    PyObject *ob_item[1];    /* ob_item contains space for 'ob_size' elements.     * Items must normally not be NULL, except during construction when     * the tuple is not yet visible outside the function that builds it.     */} PyTupleObject;

PS: 元组(tuple)实现的源码文件是 tupleobject.h 和 tupleobject.c。
tuple和list类似,实质也是一个数组,然而空间大小固定。不同于个别数组,Python 的 tuple 做了许多优化,来晋升在程序中的效率。

总结

本文具体介绍了Python内置数据类型中的列表(list)和元组(tuple)。特地是列表,它的新增元素和删除元素的办法很多,各种办法之间还有许多不同,须要在应用时特地留神。对于不波及批改元素操作的场景,优先应用元组。因为它的性能更好,所占空间更少。

全网同名【码农飞哥】。不积跬步,无以至千里,享受分享的高兴
我是码农飞哥,再次感谢您读完本文