列表(list),可以简单视之为双向连结串行,以线性列的方式管理物件集合。当然,在Python中,列表是可以含有重复元素的,python的列表与c语言中的数组比较相似。
在Python中,列表可以同时存储多个元素,而程序也可以对这些数据进行整体操作。
1.列表的创建
列表主要有两种创建方式:
方式一:变量名 = [列表元素],例如:
lst = [1, 2, 'a', 1.4]
方式二:变量名 = list([列表元素]),例如:
lst = list([1, 2, 'a', 4])
lst = list((1, 2, 3, 4))
2.列表的特点
①列表元素按顺序有序排列
②索引映射唯一一个数据
③列表可以重复存储数据
④任意数据类型混搭
⑤根据需要动态分配和回收内存
3.列表的双向索引
如有一个列表如下:
lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
那我们如何取出指定的元素呢?
在计算机科学中,一般从0出发,数字逐渐递增代表某个元素,而这个数字称为索引。
对于lst的索引:
a | b | c | d | e | f | g |
0 | 1 | 2 | 3 | 4 | 5 | 6 |
即当索引为0时,代表第一个元素,当索引为n时,代表第n+1个元素。
同时,对于python的列表来说,还有另外一种索引方式:反式递减索引。
即从最后一个元素出发,其索引值为-1,逐渐向前,索引值也逐渐递减。
对于lst的索引:
a | b | c | d | e | f | g |
-7 | -6 | -5 | -4 | -3 | -2 | -1 |
即当索引为-1时,代表最后一个元素,当索引为-n时,代表倒数第n个元素。
4.列表元素的获取
在上面我们已经说了列表的索引方式,则此时我们可以使用索引和操作符[]对列表进行访问,操作格式为:
list[index]
如依旧对于上面的列表来说:
char1 = lst[2]
char2 = lst[-2]
根据列表的双向索引方式,可以很简单的得出结果为:
c
f
5.查询某元素的索引
查询某元素的索引操作:
list.index(index[, start, stop])
如对于上面的lst列表,我们需要查询c字符的索引值,则代码为:
index = lst.index('c')
print(index)
执行输出后,输出值为:
2
另外,在该函数的参数中,有start和stop参数,即表示在[start, stop)索引范围中寻找。但如果找不到的话会报错,如:
index1 = lst.index('a')
print(index1)
index2 = lst.index('a', 2, 5)
print(index2)
执行结果为:
0
Traceback (most recent call last):
File "test.py", line 2, in <module>
print(lst.index('a', 2, 5))
ValueError: 'a' is not in list
即我们在[2, 5)的索引区间范围内,找不到‘a’的存在,因此会直接报错,而如果能找到则会返回其索引值。
6.获取列表多个元素
在很多实际应用中,我们不会一个一个取出我们要的元素,而是通过切片的方式,直接取出指定的元素。(列表切片即将分成很多片,取其中的一片或几片)
切片格式为:
list[start:stop:step]
start、stop和step中的任意一个参数均可以忽略,
忽略时step默认为1,start默认为0,stop默认为最后一个元素的索引+1。
start代表切片区间的起始索引(包含)
stop代表切片区间的终止索引(不包含)
即切片区间为[start, stop)
step代表切片区间的步长,可以简单的认为取的两个元素间隔step-1个元素
而切片切除来的各个元素仍组成一个列表。
可能概念上来说稍微有点难懂,我们上点实例:
对于列表:
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
我们想把元素 2 ~ 6取出来,那么这时
start 应该为 1(区间索引从0开始!!!)
那么stop为5吗?当然不是,我们上面说过了,stop是开区间端,
所以stop应该为6,
此时的区间为[2, 6) 可相当于 [2, 5]
而我们应该取出的元素2, 3, 4, 5, 6各个元素的间隔为0,
所以步长step = 间隔元素数 + 1 = 0 + 1,为默认值,可不填。
print(lst[1:5:])
print(lst[1:6:])
输出结果为:
[2, 3, 4, 5]
[2, 3, 4, 5, 6]
此时我不想取2~6元素了,我想把列表中的奇数都取出来。
范围为整个列表,所以起始为0(含),终止为最后一个元素(含),对于start和stop均为默认值,可以不填,那么我们进行分析一下,我们取出的元素为:
1 3 5 7 9
可以发现,各个元素之间的间隔为1,那我们可以直接填写step = 1+ 1 = 2,即:
print(lst[::2])
此时输出结果为:
[1, 3, 5, 7, 9]
此时我们可以发现,step开始间隔的元素是以区间首元素为起点的,如果这时我们不需要奇数了,而需要偶数,那应该怎么设置切片区间?
对于上述列表,因为step间隔是以start为起点的,那么保持step=2不变,而如果我们区间起点为2,那么后面的数也就依次为4 6 8 10。所以代码为:
print(lst[1::2])
输出结果为:
[2, 4, 6, 8, 10]
根据上面代码可推断,当step为正数时,元素以start索引为起始,间隔step-1个元素,进行后续元素的取出。那我们的step能为负数吗?当然可以。当step为负数时,负号表示从后向前进行切片,其数值则为间隔数+1。
如:实现一个列表的反转。
当step为负数时,切片由后向前进行,而我们不想它跳过任何数字,所以step的数值为1,所以step = -1,即:
lst_fz = lst[::-1]
print(lst)
print(lst_fz)
输出结果为:
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
当step为其他负数时同上,此处不多加赘述。
7.元素的判断与遍历
(1)元素的判断:
判断格式:(关键字 in 和 not in)
element in list (元素是否存在于列表中)
element not in list (元素是否不存在于列表中)
当满足对应的表达式时,表达式值为True
现在有一个列表:
lst = [1, 4, 7, 3, 7, 5, 8, 9, 0, 11]
现在客户提出了一个需求:如果列表中有0存在,则打印 zero here,反之打印zero not here。实现为:
if 0 in lst:
print("zero here")
if 0 not in lst:
print("zero not here")
(2)元素的遍历
在我们讲解for循环章节的时候,我们说过,for...in循环是对可迭代对象进行遍历,而我们的list、str和包括后续的dict、tuple、set等类型的数据都是可迭代对象。
格式为:
for 迭代变量 in 迭代对象:
语句块
而我们的迭代变量就是相当于逐个拿到迭代对象里面的元素(从前往后)。
如有下列一个列表:
lst = [1, 2, 3, 4, 5, 6, 8, 10, 12, 15]
现在我们想挨个拿到它的元素,那么就可以用for循环对其进行遍历:
for i in lst:
print(i, end=" ")
这样输出的结果为:
1 2 3 4 5 6 8 10 12 15
8.列表元素的更改
(1)增加
append() 在列表末尾添加一个元素
extend() 在列表末尾添加至少一个元素
insert() 在列表任意位置添加一个元素
切片 在列表任意位置添加(或称为覆盖)至少一个元素
①append(object)
现有如下两个列表:
c1 = [10, 20, 30]
c2 = [100, 200]
现在我想要在c1列表末尾再加个40:
print(c1)
c1.append(40)
print(c2)
输出结果为:
[10, 20, 30]
[10, 20, 30, 40]
那么现在有个问题,列表可以作为元素添加进列表吗?
当然可以:
我们把此时的c1添加入c2中:
print(c2)
c2.append(c1)
print(c2)
print(c2[-1])
c2[-1].append(50)
print(c2[-1])
输出结果为:
[100, 200]
[100, 200, [10, 20, 30, 40]]
[10, 20, 30, 40]
[10, 20, 30, 40, 50]
所以我们可以得知,列表也可以作为元素添加进列表,且被添加进去的列表也可以进行正常的操作。
②extend(object)
extend是在列表末尾添加至少一个元素。它的参数为一个可迭代对象,如有下列两个列表:
c1 = [10, 20, 30]
c2 = [40, 50, 60, 70, 80]
我们想把c2的元素全部添加入c1中,则为:
c1.extend(c2)
我们可以把extend简单的认为是for循环与append的实现,如:
extend等效于下面的代码:
for i in iter_object:
list.append(i)
③insert(index, value)
insert即在索引为index的地方,插入值value。如有下面一个列表:
lst = [10, 30, 40, 50]
那我们想在10和30之间插入一个元素20,那么插入这个元素后20所在的索引为1,所以:
lst.insert(1, 20)
print(lst)
输出结果为:
[10, 20, 30, 40]
④切片
在此处切片即覆盖的意思,用多个元素覆盖较少元素的切片也可以使列表的元素增加。
如有如下两个列表:
c1 = [10, 20, 30]
c2 = [40, 50, 60, 70, 80, 90, 100]
有如下一个操作:
print(c1)
c1[1:] = c2
print(c1)
输出结果为:
[10, 20, 30]
[10, 40, 50, 60, 70, 80, 90, 100]
即我们将c1第二个元素之后的元素都替换成了c2。
再如:
c1 = [10, 20, 30]
c2 = [40, 50, 60, 70, 80, 90, 100]
c1[1:] = c2[3::2]
print(c1)
输出结果为:
[10, 70, 90]
c2切片后,即c2[3::2] = [70, 90]
然后我们将c1第二个元素之后的元素替换成切片后的c2,所以结果就为[10, 70, 90]。
(2)删除
remove() 一次删除一个元素,重复元素只删除第一个
pop() 删除一个指定索引上的元素,若不指定索引则删除最后一个元素
切片 至少删除一个元素
clear() 清空列表
del 删除列表对象
①remove(value)
删除值为value的第一个元素,如:
c1 = [10, 20, 30, 20, 20]
c1.remove(20)
print(c1)
输出结果为:
[10, 30, 20, 20]
②pop([index])
删除指定索引的元素,若不指定索引则删除最后一个元素,如:
c2 = [40, 50, 60, 70, 80, 90, 100]
print(c2)
c2.pop()
print(c2)
c2.pop(2)
输出结果为:
[40, 50, 60, 70, 80, 90, 100]
[40, 50, 60, 70, 80, 90]
[40, 50, 70, 80, 90]
③切片
具体同上增加操作的切片原理,如:
c2 = [40, 50, 60, 70, 80, 90, 100]
c2 = c2[3::2]
输出结果为:
[70, 90]
④clear()
清除列表中所有的元素,但列表对象依旧存在。
lst = [10, 20, 30]
lst.clear()
print(lst)
lst.append(40)
print(lst)
输出结果为:
[]
[40]
④del
del是删除整个列表对象,del删除后列表对象就被销毁了,不能再进行调用,如:
c1 = [10, 20, 30]
del c1
如果我们在销毁后依旧调用:
c1.append(10)
此时程序就会报错:
Traceback (most recent call last):
File "test.py", line 3, in <module>
c1.append(10)
NameError: name 'c1' is not defined
(3)修改
①一次修改一个值
list[index] = value
如:
c3 = [10, 20, 30, 40]
print(c3)
c3[2] = 100
print(c3)
输出结果为:
[10, 20, 30, 40]
[10, 20, 100, 40]
②一次修改多个值(通过切片实现)
list[start:stop:step] = new_list
如:
c2 = [40, 50, 60, 70, 80, 90, 100]
print(c2)
c2[2:4:] = [12, 14, 16]
print(c2)
输出结果为:
[40, 50, 60, 70, 80, 90, 100]
[40, 50, 12, 14, 16, 80, 90, 100]
(4)排序
列表可以使用内置的sort()方法,可以将所有参数默认从小到大进行排序,我们也可以指定其默认参数reverse=True,让所有参数从大到小进行排序。sort()会改变列表本身。
还可以使用sorted()函数,具体使用同上描述,但sorted()函数不会影响其列表自身的值。
(reverse=True即降序排列,reverse=False即升序排列)
如:
c4 = [9, 5, 7, 6, 3, 8, 4, 1, 2, 0]
print(c4)
c4.sort() # 升序排列
print(c4)
c4.sort(reverse=True) # 降序排列
print(c4)
输出结果为:
[9, 5, 7, 6, 3, 8, 4, 1, 2, 0]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
c5 = sorted(c4) # 只是赋值,并未改变列表c4
print(c4)
print(c5)
c5 = sorted(c4, reverse=True)
print(c5)
输出结果为:
[9, 5, 7, 6, 3, 8, 4, 1, 2, 0]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
9.列表中元素的个数
列表中元素的个数可以使用函数len()求,如:
lst = [1, 2, 3, 4, 5, 6, 7]
print(len(lst))
输出结果为:
7
10.列表生成式
列表生成式可以简单认为在创建列表时,直接在列表内部将元素生成出来,如见下面一个例子:
lst = [i for i in range(10)]
print(lst)
输出结果为:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
上面的[i for i in range(10)]即列表生成式,要理解它,那么我们必须将lst拆分开来看,首先最前面的 i 是指列表中的元素,而for i in range(10)是指 i 所指的元素。
我们再看一个例子:
lst = [i * i for i in range(5)]
print(lst)
输出结果为:
[0, 1, 4, 9, 16]
即 i * i 是列表中的元素,而for i in range(5)是列表中 i 的遍历。
列表生成式还可以跟if语句结合:
lst = [i for i in range(10) if i % 2 == 0]
print(lst)
输出结果为:
[0, 2, 4, 6, 8]
即 i 是列表中的元素,for i in range(10)是对 i 的遍历,而 if i % 2 == 0是对 i 的判定,只有满足该条件表达式,才会存在 i 中。
当然列表表达式还有其他很广的应用,这里再举一个例子:
import random
print("、".join([str(i) for i in range(100) if random.randint(0, i) == i]))
某一次的输出结果为:
0、1、2、3、11、40