6  数据结构:列表

6.1 列表:数据的”购物车”

想象一下,当我们去超市购物时,会把不同的商品放入购物车。Python中的列表就像这样一个”购物车”,可以存放多个数据。

6.1.1 什么是列表?

列表是Python中最常用的数据结构,用方括号 [] 来表示,数据之间用逗号 , 分隔。

# 创建一个购物清单
shopping_list = ["牛奶", "面包", "鸡蛋", "水果"]
print("我的购物清单:", shopping_list)

# 创建一个成绩单
scores = [95, 88, 92, 87, 90]
print("小明的成绩:", scores)
我的购物清单: ['牛奶', '面包', '鸡蛋', '水果']
小明的成绩: [95, 88, 92, 87, 90]

💡 小贴士 列表就像一个容器,可以存放各种类型的数据,但最好在一个列表中存放相同类型的数据,这样更容易管理。

6.1.2 访问列表中的元素

6.1.2.1 使用索引(下标)

列表中的每个元素都有一个位置编号,我们称之为索引。需要注意的是,Python中的索引从0开始计数:

  • 第一个元素的索引是0
  • 第二个元素的索引是1
  • 最后一个元素可以用-1表示
  • 倒数第二个元素可以用-2表示
students = ["小明", "小红", "小华", "小李", "小张"]

print("第一名同学是:", students[0])  # 输出:小明
print("最后一名同学是:", students[-1])  # 输出:小张
print("倒数第二名同学是:", students[-2])  # 输出:小李
第一名同学是: 小明
最后一名同学是: 小张
倒数第二名同学是: 小李

6.1.2.2 切片:取出多个元素

如果想一次性取出多个元素,可以使用切片操作。语法是 列表[开始:结束]

# 创建一个一周的日程表
weekly_schedule = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]

# 取出工作日
workdays = weekly_schedule[0:5]  # 或者简写为 weekly_schedule[:5]
print("工作日:", workdays)

# 取出周末
weekend = weekly_schedule[5:7]  # 或者简写为 weekly_schedule[5:]
print("周末:", weekend)

# 反转整个列表
reversed_week = weekly_schedule[::-1]
print("反转后的日程表:", reversed_week)
工作日: ['周一', '周二', '周三', '周四', '周五']
周末: ['周六', '周日']
反转后的日程表: ['周日', '周六', '周五', '周四', '周三', '周二', '周一']

🌟 要点总结

  1. 列表用 [] 创建,元素用逗号分隔
  2. 索引从0开始计数
  3. 可以用负数索引从后往前数
  4. 切片可以取出多个元素
  5. 列表可以存储任何类型的数据
  6. 使用 len() 获取列表长度
  7. 使用 in 检查元素是否存在

6.2 列表的基本操作

就像整理书包一样,我们经常需要对列表进行添加、删除、修改等操作。让我们来学习这些基本操作!

6.2.1 修改列表元素

想象你在整理课程表,有时候需要更换某一节课:

# 创建一个课程表
schedule = ["语文", "数学", "英语", "物理", "化学"]
print("原始课程表:", schedule)

# 把第一节课改成"体育"
schedule[0] = "体育"
print("修改后的课程表:", schedule)

# 一次性修改多节课
schedule[1:3] = ["音乐", "美术"]  # 把第2-3节课改成音乐和美术
print("批量修改后的课程表:", schedule)
原始课程表: ['语文', '数学', '英语', '物理', '化学']
修改后的课程表: ['体育', '数学', '英语', '物理', '化学']
批量修改后的课程表: ['体育', '音乐', '美术', '物理', '化学']

6.2.2 添加新元素

有三种常用的添加元素的方法:

  1. append(): 在末尾添加一个元素(就像在书包最后放一本书)
  2. insert(): 在指定位置插入元素(就像在书包中间塞一本书)
  3. extend(): 一次性添加多个元素(就像把另一个书包的书都放进来)
# 创建一个待办事项列表
todos = ["做作业", "看书"]
print("原始待办事项:", todos)

# 在末尾添加一项
todos.append("打篮球")
print("添加一项后:", todos)

# 在指定位置插入一项
todos.insert(1, "吃午饭")  # 在第二个位置插入
print("插入一项后:", todos)

# 一次性添加多项
more_todos = ["听音乐", "洗衣服"]
todos.extend(more_todos)
print("添加多项后:", todos)
原始待办事项: ['做作业', '看书']
添加一项后: ['做作业', '看书', '打篮球']
插入一项后: ['做作业', '吃午饭', '看书', '打篮球']
添加多项后: ['做作业', '吃午饭', '看书', '打篮球', '听音乐', '洗衣服']

6.2.3 删除元素

有三种常用的删除方法:

  1. remove(): 删除指定的元素(知道要删除什么)
  2. pop(): 删除指定位置的元素(知道要删除第几个)
  3. del: 可以删除一个或多个元素
# 创建一个购物清单
shopping = ["苹果", "香蕉", "橙子", "西瓜", "葡萄", "草莓"]
print("原始购物清单:", shopping)

# 删除指定商品
shopping.remove("西瓜")  # 删除西瓜
print("删除西瓜后:", shopping)

# 删除最后一个商品并显示它
last_item = shopping.pop()  # 不指定位置默认删除最后一个
print("删除的商品是:", last_item)
print("删除后的清单:", shopping)

# 删除多个商品
del shopping[1:3]  # 删除第2个到第3个商品
print("批量删除后:", shopping)
原始购物清单: ['苹果', '香蕉', '橙子', '西瓜', '葡萄', '草莓']
删除西瓜后: ['苹果', '香蕉', '橙子', '葡萄', '草莓']
删除的商品是: 草莓
删除后的清单: ['苹果', '香蕉', '橙子', '葡萄']
批量删除后: ['苹果', '葡萄']

6.2.4 排序

就像整理扑克牌一样,我们可以对列表进行排序:

# 创建一个成绩单
scores = [85, 92, 78, 95, 88]
print("原始成绩:", scores)

# 升序排序(从小到大)
scores.sort()
print("升序排序后:", scores)

# 降序排序(从大到小)
scores.sort(reverse=True)
print("降序排序后:", scores)

# 对名字进行排序
names = ["小明", "小红", "小华", "小李"]
names.sort()
print("按字母顺序排序:", names)
原始成绩: [85, 92, 78, 95, 88]
升序排序后: [78, 85, 88, 92, 95]
降序排序后: [95, 92, 88, 85, 78]
按字母顺序排序: ['小华', '小明', '小李', '小红']

6.2.5 数学运算

当列表中都是数字时,我们可以进行一些数学运算:

scores = [85, 92, 78, 95, 88, 90, 87, 91, 83, 89]

# 计算平均分
average = sum(scores) / len(scores)
# 找出最高分和最低分
highest = max(scores)
lowest = min(scores)

print(f"班级成绩分析:")
print(f"- 平均分:{average:.1f}")
print(f"- 最高分:{highest}")
print(f"- 最低分:{lowest}")
print(f"- 参加考试人数:{len(scores)}")
班级成绩分析:
- 平均分:87.8
- 最高分:95
- 最低分:78
- 参加考试人数:10

6.2.6 实用技巧

  1. 检查元素是否存在
fruits = ["苹果", "香蕉", "橙子"]
if "苹果" in fruits:
    print("有苹果可以吃!")
有苹果可以吃!
  1. 计算元素出现次数
numbers = [1, 2, 3, 2, 4, 2, 5]
count_2 = numbers.count(2)  # 统计2出现的次数
print(f"数字2出现了{count_2}次")
数字2出现了3次
  1. 找出元素位置
students = ["小明", "小红", "小华"]
position = students.index("小红")  # 找出"小红"的位置
print(f"小红在第{position + 1}个位置")
小红在第2个位置

6.2.7 练习题

  1. 创建一个你的课程表,然后:
    • 把第一节课换成自习
    • 在第三节课后插入午休
    • 删除最后一节课
    • 按字母顺序排序所有课程
  2. 记录一周的温度,然后:
    • 计算平均温度
    • 找出最高温和最低温
    • 把温度从高到低排序
  3. 管理一个图书清单:
    • 添加三本新书
    • 删除看完的书
    • 在指定位置插入一本书
    • 对所有书名按字母排序

🌟 要点总结

  1. 修改元素:直接赋值或切片赋值
  2. 添加元素:append()、insert()、extend()
  3. 删除元素:remove()、pop()、del
  4. 排序:sort() 可以升序或降序
  5. 数学运算:sum()求和、len()计数、max()/min()找最值
  6. 多使用 in 来检查元素是否存在
  7. count() 可以统计元素出现次数

6.3 元组:不可变的列表

想象你在参加考试,考卷上的题目和答案是不能更改的。元组就像这样,一旦创建就不能修改的数据集合。

6.3.1 什么是元组?

元组和列表很像,但有一个重要区别:

  • 列表使用 [] 创建,可以随意修改
  • 元组使用 () 创建,创建后不能修改
# 创建一个表示RGB颜色的元组
red = (255, 0, 0)      # 红色
green = (0, 255, 0)    # 绿色
blue = (0, 0, 255)     # 蓝色

print("红色的RGB值:", red)
print("绿色的RGB值:", green)
print("蓝色的RGB值:", blue)

# 尝试修改元组会导致错误
try:
    red[0] = 100  # 这会产生错误
except TypeError as e:
    print("\n不能修改元组!错误信息:", e)
红色的RGB值: (255, 0, 0)
绿色的RGB值: (0, 255, 0)
蓝色的RGB值: (0, 0, 255)

不能修改元组!错误信息: 'tuple' object does not support item assignment

6.3.2 元组的常见用途

表示固定的数据组合

# 表示一个学生的基本信息(学号,姓名,年龄)
student = (1001, "小明", 16)
print(f"学号:{student[0]}")
print(f"姓名:{student[1]}")
print(f"年龄:{student[2]}")

# 表示地理坐标(经度,纬度)
beijing = (116.407396, 39.904200)
print(f"\n北京的坐标是:经度 {beijing[0]},纬度 {beijing[1]}")
学号:1001
姓名:小明
年龄:16

北京的坐标是:经度 116.407396,纬度 39.9042

6.3.3 元组的优点

  1. 数据安全:不会被意外修改
  2. 代码可靠:保证数据的完整性
  3. 性能更好:比列表处理速度快

6.3.4 元组的操作

虽然不能修改元组的内容,但我们可以:

# 创建一个考试成绩元组
scores = (85, 92, 78, 95, 88)

# 1. 获取长度
print(f"考试科目数:{len(scores)}")

# 2. 查找最大和最小值
print(f"最高分:{max(scores)}")
print(f"最低分:{min(scores)}")

# 3. 计算平均值
print(f"平均分:{sum(scores) / len(scores):.1f}")

# 4. 检查元素是否存在
print(f"是否有满分:{100 in scores}")

# 5. 元组切片
print(f"前三科成绩:{scores[:3]}")
考试科目数:5
最高分:95
最低分:78
平均分:87.6
是否有满分:False
前三科成绩:(85, 92, 78)

6.3.5 练习题

  1. 创建一个表示你的个人信息的元组(姓名、年龄、身高),然后:
    • 打印出所有信息
    • 尝试修改信息(观察错误)
    • 使用切片获取部分信息

🌟 要点总结

  1. 元组用 () 创建,列表用 [] 创建
  2. 元组创建后不能修改(不可变)
  3. 元组常用于表示固定的数据组合
  4. 可以使用索引和切片访问元组元素
  5. 元组比列表更安全,性能更好
  6. 使用解包可以方便地获取元组中的值