Python从0到100(七):Python列表介绍及运用

一、 列表概述

问题描述:

假设一个班有100个学生,如果每个变量存放一个学生的姓名,是不是很麻烦?如果有一千个学生甚至更多,那该怎么办呢?

列表 是Python中的一种数据结构,它可以存储不同类型的数据。例如:A = [1,'xiaoWang','a', [2, 'b']] 列表索引是从0开始的,我们可以通过下标索引的方式来访问列表中的值。

python 复制代码
A = ['xiaoWang', 'xiaoZhang', 'xiaoHua']
print(A[0])
print(A[1])

在Python中,列表是由一系元素按特定顺序构成的数据序列 ,这样就意味着定义一个列表类型的变量,可以保存多个数据 ,而且允许有重复的数据

在Python中,可以使用[]字面量语法来定义列表,列表中的多个元素用逗号进行分隔,代码如下所示。

python 复制代码
items1 = [35, 12, 99, 68, 55, 87]
items2 = ['Python', 'Java', 'Go', 'Kotlin']

除此以外,还可以通过Python内置的list函数将其他序列变成列表。准确的说,list并不是一个普通的函数,它是创建列表对象的构造器(后面会讲到对象和构造器这两个概念)。

python 复制代码
items1 = list(range(1, 10))
print(items1)    # [1, 2, 3, 4, 5, 6, 7, 8, 9]
items2 = list('hello')
print(items2)    # ['h', 'e', 'l', 'l', 'o']

需要说明的是,列表是一种可变数据类型,也就是说列表可以添加元素、删除元素、更新元素,这一点跟我们上一课讲到的字符串有着鲜明的差别。字符串是一种不可变数据类型,也就是说对字符串做拼接、重复、转换大小写、修剪空格等操作的时候会产生新的字符串,原来的字符串并没有发生任何改变。

列表的运算符

和字符串类型一样,列表也支持拼接、重复、成员运算、索引和切片以及比较运算,对此我们不再进行赘述,请大家参考下面的代码。

python 复制代码
items1 = [35, 12, 99, 68, 55, 87]
items2 = [45, 8, 29]

# 列表的拼接
items3 = items1 + items2
print(items3)    # [35, 12, 99, 68, 55, 87, 45, 8, 29]

# 列表的重复
items4 = ['hello'] * 3
print(items4)    # ['hello', 'hello', 'hello']

# 列表的成员运算
print(100 in items3)        # False
print('hello' in items4)    # True

# 获取列表的长度(元素个数)
size = len(items3)
print(size)                 # 9

# 列表的索引
print(items3[0], items3[-size])        # 35 35
items3[-1] = 100
print(items3[size - 1], items3[-1])    # 100 100

# 列表的切片
print(items3[:5])          # [35, 12, 99, 68, 55]
print(items3[4:])          # [55, 87, 45, 8, 100]
print(items3[-5:-7:-1])    # [55, 68]
print(items3[::-2])        # [100, 45, 55, 99, 35]

# 列表的比较运算
items5 = [1, 2, 3, 4]
items6 = list(range(1, 5))
# 两个列表比较相等性比的是对应索引位置上的元素是否相等
print(items5 == items6)    # True
items7 = [3, 2, 1]
# 两个列表比较大小比的是对应索引位置上的元素的大小
print(items5 <= items7)    # True

值得一提的是,由于列表是可变类型,所以通过索引操作既可以获取列表中的元素,也可以更新列表中的元素。对列表做索引操作一样要注意索引越界的问题,对于有N个元素的列表,正向索引的范围是0N-1,负向索引的范围是-1-N,如果超出这个范围,将引发IndexError异常,错误信息为:list index out of range

二、列表元素的遍历

如果想逐个取出列表中的元素,可以使用for循环的,有以下两种做法。

方法一:

python 复制代码
items = ['Python', 'Java', 'Go', 'Kotlin']

for index in range(len(items)):
    print(items[index])

方法二:

python 复制代码
items = ['Python', 'Java', 'Go', 'Kotlin']

for item in items:
    print(item)

讲到这里,我们可以用列表的知识来重构上面"掷色子统计每个点数出现次数"的代码。

python 复制代码
import random

counters = [0] * 6
for _ in range(6000):
    face = random.randint(1, 6)
    counters[face - 1] += 1
for face in range(1, 7):
    print(f'{face}点出现了{counters[face - 1]}次')

上面的代码中,我们用counters列表中的六个元素分别表示1到6的点数出现的次数,最开始的时候六个元素的值都是0。接下来用随机数模拟掷色子,如果摇出1点counters[0]的值加1,如果摇出2点counters[1]的值加1,以此类推。大家感受一下,这段代码是不是比之前的代码要简单优雅很多。

三、列表的常见操作

和字符串一样,列表类型的方法也很多,下面为大家讲解比较重要的方法。

1.在列表中增加元素

在列表中增加元素的方式有多种,具体如下:

  • 通过append可以向列表添加元素
  • 通过extend可以将另一个列表的元素添加到列表中。
  • 通过insert在指定位置index前插入元素object。

2.在列表中查找元素

在列表中查找元素的方法包括:

  • in(存在),如果存在那么结果为true,否则为false。
  • not in(不存在),如果不存在那么结果为true,否则false。

3.在列表中修改元素

列表元素的修改,也是通过下标来实现的。

python 复制代码
 A = ['xiaoWang','xiaoZhang','xiaoHua']
 A[1] = 'xiaoLu'

4.在列表中删除元素

列表元素的常用删除方法有三种,具体如下:

  • del:根据下标进行删除
  • pop:删除最后一个元素
  • remove:根据元素的值进行删除

四、列表的排序操作

列表的排序可以通过下面两个方法实现:

  • sort方法:列表的元素按照特定顺序排列。
  • reverse方法:将列表逆置。

1.元素位置和次数

列表类型的index方法可以查找某个元素在列表中的索引位置;因为列表中允许有重复的元素,所以列表类型提供了count方法来统计一个元素在列表中出现的次数。请看下面的代码。

python 复制代码
items = ['Python', 'Java', 'Java', 'Go', 'Kotlin', 'Python']

# 查找元素的索引位置
print(items.index('Python'))       # 0
print(items.index('Python', 2))    # 5
# 注意:虽然列表中有'Java',但是从索引为3这个位置开始后面是没有'Java'的
print(items.index('Java', 3))      # ValueError: 'Java' is not in list

再来看看下面这段代码。

python 复制代码
items = ['Python', 'Java', 'Java', 'Go', 'Kotlin', 'Python']

# 查找元素出现的次数
print(items.count('Python'))    # 2
print(items.count('Go'))        # 1
print(items.count('Swfit'))     # 0

2.元素排序和反转

列表的sort操作可以实现列表元素的排序,而reverse操作可以实现元素的反转,代码如下所示。

python 复制代码
items = ['Python', 'Java', 'Go', 'Kotlin', 'Python']

# 排序
items.sort()
print(items)    # ['Go', 'Java', 'Kotlin', 'Python', 'Python']
# 反转
items.reverse()
print(items)    # ['Python', 'Python', 'Kotlin', 'Java', 'Go']

五、列表的生成式

在Python中,列表还可以通过一种特殊的字面量语法来创建,这种语法叫做生成式。我们给出两段代码,大家可以做一个对比,看看哪一种方式更加简单优雅。

通过for循环为空列表添加元素。

python 复制代码
# 创建一个由1到9的数字构成的列表
items1 = []
for x in range(1, 10):
    items1.append(x)
print(items1)

# 创建一个由'hello world'中除空格和元音字母外的字符构成的列表
items2 = []
for x in 'hello world':
    if x not in ' aeiou':
        items2.append(x)
print(items2)

# 创建一个由个两个字符串中字符的笛卡尔积构成的列表
items3 = []
for x in 'ABC':
    for y in '12':
        items3.append(x + y)
print(items3)

通过生成式创建列表。

python 复制代码
# 创建一个由1到9的数字构成的列表
items1 = [x for x in range(1, 10)]
print(items1)    # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 创建一个由'hello world'中除空格和元音字母外的字符构成的列表
items2 = [x for x in 'hello world' if x not in ' aeiou']
print(items2)    # ['h', 'l', 'l', 'w', 'r', 'l', 'd']

# 创建一个由个两个字符串中字符的笛卡尔积构成的列表
items3 = [x + y for x in 'ABC' for y in '12']
print(items3)    # ['A1', 'A2', 'B1', 'B2', 'C1', 'C2']

下面这种方式不仅代码简单优雅,而且性能也优于上面使用for循环和append方法向空列表中追加元素的方式。可以简单跟大家交待下为什么生成式拥有更好的性能,那是因为Python解释器的字节码指令中有专门针对生成式的指令(LIST_APPEND指令);而for循环是通过方法调用(LOAD_METHODCALL_METHOD指令)的方式为列表添加元素,方法调用本身就是一个相对耗时的操作。对这一点不理解也没有关系,记住"强烈建议用生成式语法来创建列表"这个结论就可以了。

嵌套的列表

Python语言没有限定列表中的元素必须是相同的数据类型,也就是说一个列表中的元素可以任意的数据类型,当然也包括列表。如果列表中的元素又是列表,那么我们可以称之为嵌套的列表。嵌套的列表可以用来表示表格或数学上的矩阵,例如:我们想保存5个学生3门课程的成绩,可以定义一个保存5个元素的列表保存5个学生的信息,而每个列表元素又是3个元素构成的列表,分别代表3门课程的成绩。但是,一定要注意下面的代码是有问题的。

python 复制代码
scores = [[0] * 3] * 5
print(scores)    # [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

看上去我们好像创建了一个5 * 3的嵌套列表,但实际上当我们录入第一个学生的第一门成绩后,你就会发现问题来了,我们看看下面代码的输出。

python 复制代码
# 嵌套的列表需要多次索引操作才能获取元素
scores[0][0] = 95
print(scores)
# [[95, 0, 0], [95, 0, 0], [95, 0, 0], [95, 0, 0], [95, 0, 0]]

我们不去过多的解释为什么会出现这样的问题,如果想深入研究这个问题,可以通过Python Tutor网站的可视化代码执行功能,看看创建列表时计算机内存中发生了怎样的变化,下面的图就是在这个网站上生成的。建议大家不去纠结这个问题,现阶段只需要记住不能用[[0] * 3] * 5]这种方式来创建嵌套列表就行了。那么创建嵌套列表的正确做法是什么呢,下面的代码会给你答案。

python 复制代码
scores = [[0] * 3 for _ in range(5)]
scores[0][0] = 95
print(scores)
# [[95, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
相关推荐
2025年一定要上岸4 分钟前
【Django】-10- 单元测试和集成测试(下)
数据库·后端·python·单元测试·django·集成测试
程序员海军16 分钟前
这才是Coding该有的样子!重新定义编程显示器
前端·后端
_風箏18 分钟前
Shell【脚本 05】交互式Shell脚本编写及问题处理([: ==: unary operator expected)[: ==: 期待一元表达式
后端
Cache技术分享18 分钟前
151. Java Lambda 表达式 - 使用 Consumer 接口处理对象
前端·后端
用户5769053080119 分钟前
Python实现一个类似MybatisPlus的简易SQL注解
后端·python
hello早上好22 分钟前
Spring AOP静态与动态通知的协作原理
后端·架构
MacroZheng39 分钟前
狂揽9.3k star!号称终端版Postman项目,太炫酷了!
java·spring boot·后端
Lemon程序馆1 小时前
Mysql 常见的性能分析手段
数据库·后端·mysql
东阳马生架构1 小时前
Dubbo源码—1.服务发布的主要流程
后端
meiguiyulu1 小时前
深入理解 CountdownLatch:多线程同步的得力助手
后端