当前位置:首页>python>Python从入门到精通day08

Python从入门到精通day08

  • 2026-10-21 13:27:10
Python从入门到精通day08

Python从入门到精通day08

常用数据结构之列表-1

在正式学习本节课内容前,我们先做一个小任务:将一颗骰子掷6000次,统计每种点数(1-6点)出现的次数。结合之前学的分支和循环知识,大家应该能轻松写出下面的代码——用1-6的随机数模拟掷骰子,再用6个变量分别记录每个点数的出现次数。

"""将一颗色子掷6000次,统计每种点数出现的次数Author: 南阳Version: 1.0"""import randomf1 = 0f2 = 0f3 = 0f4 = 0f5 = 0f6 = 0for _ inrange(6000):    face = random.randrange(1, 7)if face == 1:        f1 += 1elif face == 2:        f2 += 1elif face == 3:        f3 += 1elif face == 4:        f4 += 1elif face == 5:        f5 += 1else:        f6 += 1print(f'1点出现了{f1}次')print(f'2点出现了{f2}次')print(f'3点出现了{f3}次')print(f'4点出现了{f4}次')print(f'5点出现了{f5}次')print(f'6点出现了{f6}次')

这段代码能完成任务,但问题很明显:过于繁琐冗余。如果需求变成“掷两颗骰子(点数范围2-12)”,我们就要定义11个变量、写11个分支,代码量会成倍增加,后续维护也很麻烦。

看到这里,大家肯定会想:有没有办法用一个变量保存多个数据?能不能用统一的代码批量操作这些数据?答案是肯定的!Python中的「容器型数据类型」就能解决这个问题,今天我们先学习最常用的一种——列表(list)。

创建列表

列表是Python中最基础的有序容器,能按特定顺序存储多个数据(元素)。简单理解:列表就像一个“数据盒子”,可以把多个数据装进同一个变量里,还能按顺序管理这些数据。

列表的核心特点:

  • 有序性:元素按添加顺序排列,每个元素有固定的“位置”(后续会讲的“索引”);

  • 可重复:同一个元素可以在列表中出现多次;

  • 多类型兼容:支持存储整数、字符串、布尔值等不同类型的元素(不推荐,后续操作会很麻烦,建议一个列表存同类型数据)。

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

items1 = [35, 12, 99, 68, 55, 35, 87]items2 = ['Python', 'Java', 'Go', 'Kotlin']items3 = [100, 12.3, 'Python', True]print(items1)  # [35, 12, 99, 68, 55, 35, 87]print(items2)  # ['Python', 'Java', 'Go', 'Kotlin']print(items3)  # [100, 12.3, 'Python', True]

说明:列表中可以有重复元素,例如items1中的35;列表中可以有不同类型的元素,例如items3中有int类型、float类型、str类型和bool类型的元素,但是我们通常并不建议将不同类型的元素放在同一个列表中,主要是操作起来极为不便。

我们可以使用type函数来查看变量的类型,有兴趣的小伙伴可以自行查看上面的变量items1到底是什么类型。因为列表可以保存多个元素,它是一种容器型的数据类型,所以我们在给列表类型的变量起名字时,变量名通常用复数形式的单词。

除此以外,还可以通过 Python 内置的list函数将其他序列变成列表。准确的说,list并不是一个普通的函数,它是创建列表对象的构造器,后面的课程会为大家介绍对象和构造器这些概念。

items4 = list(range(1, 10))items5 = list('hello')print(items4)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]print(items5)  # ['h', 'e', 'l', 'l', 'o']

说明:range(1, 10)会产生1到9的整数序列,给到list构造器中,会创建出由1到9的整数构成的列表。字符串是字符构成的序列,上面的list('hello')用字符串hello的字符作为列表元素,创建了列表对象。

列表的核心运算

列表支持多种运算符,掌握这些运算能快速实现批量数据操作,是列表的核心知识点。下面逐个讲解常用运算:

1. 拼接运算(+ / +=)

用+可将两个列表的元素拼接成一个新列表;用+=可将后一个列表的元素“追加”到前一个列表中(修改原列表)。

items5 = [35, 12, 99, 45, 66]items6 = [45, 58, 29]items7 = ['Python', 'Java', 'JavaScript']print(items5 + items6)  # [35, 12, 99, 45, 66, 45, 58, 29]print(items6 + items7)  # [45, 58, 29, 'Python', 'Java', 'JavaScript']items5 += items6print(items5)  # [35, 12, 99, 45, 66, 45, 58, 29]

2. 重复运算(*)

用*可将列表元素重复指定次数,生成新列表。常用场景:快速创建元素相同的列表(如初始化多个计数变量)。

print(items6 * 3)  # [45, 58, 29, 45, 58, 29, 45, 58, 29]print(items7 * 2)  # ['Python', 'Java', 'JavaScript', 'Python', 'Java', 'JavaScript']

3. 成员运算(in / not in)

判断一个元素是否在列表中,结果为布尔值(True/False),是日常开发中高频使用的判断逻辑。

print(29in items6)  # Trueprint(99in items6)  # Falseprint('C++'notin items7)     # Trueprint('Python'notin items7)  # False

4. 索引运算(列表[索引])【重点】

列表是有序序列,每个元素都有固定的“位置编号”,称为索引。通过索引能精准访问或修改单个元素,这是列表最核心的操作之一。

核心规则:索引的两种表示方式

假设列表有N个元素,索引分为「正向索引」和「反向索引」:

  • 正向索引:从左到右,从0开始(第一个元素索引为0,第二个为1,...,最后一个为N-1);

  • 反向索引:从右到左,从-1开始(最后一个元素索引为-1,倒数第二个为-2,...,第一个为-N)。

items8 = ['apple', 'waxberry', 'pitaya', 'peach', 'watermelon']print(items8[0])   # appleprint(items8[2])   # pitayaprint(items8[4])   # watermelonitems8[2] = 'durian'print(items8)      # ['apple', 'waxberry', 'durian', 'peach', 'watermelon']print(items8[-5])  # 'apple'print(items8[-4])  # 'waxberry'print(items8[-1])  # watermelonitems8[-4] = 'strawberry'print(items8)      # ['apple', 'strawberry', 'durian', 'peach', 'watermelon']

在使用索引运算的时候要避免出现索引越界的情况,对于上面的items8,如果我们访问items8[5]或items8[-6],就会引发IndexError错误,导致程序崩溃,对应的错误信息是:list index out of range,翻译成中文就是“数组索引超出范围”。因为对于只有五个元素的列表items8,有效的正向索引是0到4,有效的反向索引是-1到-5。

5. 切片运算(列表[start:end:stride])【重点】

如果希望一次性访问列表中的多个元素,我们可以使用切片运算。切片运算是形如[start:end:stride]的运算符,其中start代表访问列表元素的起始位置,end代表访问列表元素的终止位置(终止位置的元素无法访问),而stride则代表了跨度,简单的说就是位置的增量,比如我们访问的第一个元素在start位置,那么第二个元素就在start + stride位置,当然start + stride要小于end。我们给上面的代码增加下面的语句,来使用切片运算符访问列表元素。

print(items8[1:3:1])     # ['strawberry', 'durian']print(items8[0:3:1])     # ['apple', 'strawberry', 'durian']print(items8[0:5:2])     # ['apple', 'durian', 'watermelon']print(items8[-4:-2:1])   # ['strawberry', 'durian']print(items8[-2:-6:-1])  # ['peach', 'durian', 'strawberry', 'apple']

提醒:大家可以看看上面代码中的最后一行,想一想当跨度为负数时,切片运算是如何访问元素的。

如果start值等于0,那么在使用切片运算符时可以将其省略;如果end值等于N,N代表列表元素的个数,那么在使用切片运算符时可以将其省略;如果stride值等于1,那么在使用切片运算符时也可以将其省略。所以,下面的代码跟上面的代码作用完全相同。

print(items8[1:3])     # ['strawberry', 'durian']print(items8[:3:1])    # ['apple', 'strawberry', 'durian']print(items8[::2])     # ['apple', 'durian', 'watermelon']print(items8[-4:-2])   # ['strawberry', 'durian']print(items8[-2::-1])  # ['peach', 'durian', 'strawberry', 'apple']

事实上,我们还可以通过切片操作修改列表中的元素,例如我们给上面的代码再加上一行,大家可以看看这里的输出。

items8[1:3] = ['x', 'o']print(items8)  # ['apple', 'x', 'o', 'peach', 'watermelon']

6. 关系运算(== / != / < / > 等)

两个列表还可以做关系运算,我们可以比较两个列表是否相等,也可以给两个列表比大小,代码如下所示。

nums1 = [1, 2, 3, 4]nums2 = list(range(1, 5))nums3 = [3, 2, 1]print(nums1 == nums2)  # Trueprint(nums1 != nums2)  # Falseprint(nums1 <= nums3)  # Trueprint(nums2 >= nums3)  # False

说明:上面的nums1和nums2对应元素完全相同,所以==运算的结果是True。nums2和nums3的比较,由于nums2的第一个元素1小于nums3的第一个元素3,所以nums2 >= nums3比较的结果是False。两个列表的关系运算在实际工作并不那么常用,如果实在不理解就跳过吧,不用纠结。

元素的遍历

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

方法一:在循环结构中通过索引运算,遍历列表元素。

languages = ['Python', 'Java', 'C++', 'Kotlin']for index inrange(len(languages)):print(languages[index])

输出:

PythonJavaC++Kotlin

说明:上面的len函数可以获取列表元素的个数N,而range(N)则构成了从0到N-1的范围,刚好可以作为列表元素的索引。

方法二:直接对列表做循环,循环变量就是列表元素的代表。

languages = ['Python', 'Java', 'C++', 'Kotlin']for language in languages:print(language)

输出:

PythonJavaC++Kotlin

总结实战:用列表重构骰子统计代码

学到这里,我们可以用列表优化本节课开头的“骰子统计”代码了。对比基础版,列表能实现“一个变量存多个数据+批量操作”,代码会简洁很多:

"""将一颗色子掷6000次,统计每种点数出现的次数Author: 南阳Version: 1.1"""import randomcounters = [0] * 6# 模拟掷色子记录每种点数出现的次数for _ inrange(6000):    face = random.randrange(1, 7)    counters[face - 1] += 1# 输出每种点数出现的次数for face inrange(1, 7):print(f'{face}点出现了{counters[face - 1]}次')

优化逻辑解析

  1. 用[0] * 6快速创建6个0的列表,避免定义6个独立变量;

  2. 骰子点数是1-6,列表索引是0-5,用face - 1实现“点数→索引”的精准映射;

  3. 无需冗长的分支结构,一行counters[face - 1] += 1完成批量计数;

  4. 如果后续需要统计两颗骰子的点数,只需修改列表长度(如[0] * 11)和点数范围,核心逻辑不变,扩展性极强。

对比两个版本的代码,大家能明显感受到:列表+循环的组合,能极大简化批量数据的处理逻辑,让代码更简洁、优雅、易维护。这就是列表(容器类型)的核心价值!

 今日总结

最新文章

随机文章