欢迎光临
我们一直在努力

第8课:Python|列表List详解【增删改查、遍历与嵌套列表实战】

在这里插入图片描述

文章目录

  • 📖 开篇导读
  • 🎯 学习目标
  • 📚 知识点理论精讲
    • 一、列表的定义与特性
      • 1.1 什么是列表
      • 1.2 列表的核心特性
      • 1.3 列表的创建方式
    • 二、列表的常用操作
      • 2.1 访问元素:索引与切片
      • 2.2 修改元素
      • 2.3 添加元素
      • 2.4 删除元素
      • 2.5 查询与统计
      • 2.6 排序与反转
      • 2.7 复制列表:浅拷贝与深拷贝
        • 浅拷贝:只复制第一层,内部嵌套的对象还是引用
        • 深拷贝:递归复制所有层级,完全独立
    • 三、遍历列表的多种方式
      • 3.1 直接遍历元素
      • 3.2 遍历索引(使用range和len)
      • 3.3 同时遍历索引和元素(enumerate)
      • 3.4 并行遍历多个列表(zip)
      • 3.5 倒序遍历
    • 四、列表推导式(List Comprehension)
      • 4.1 基本语法
      • 4.2 基础示例
      • 4.3 嵌套循环的列表推导
      • 4.4 条件表达式(三元)结合
      • 4.5 列表推导式 vs map/filter
    • 五、嵌套列表(多维列表)
      • 5.1 创建二维列表
      • 5.2 访问和修改嵌套列表
      • 5.3 应用:矩阵转置
    • 六、列表的高级技巧与性能
      • 6.1 使用`*`重复列表的陷阱
      • 6.2 列表作为栈和队列
      • 6.3 列表的内存动态分配
  • 💻 代码案例实操
    • 案例1:待办事项管理器(增删改查综合)
    • 案例2:列表排序与筛选——学生成绩处理
    • 案例3:列表推导式——数据转换与过滤
    • 案例4:深浅拷贝深度剖析
    • 案例5:嵌套列表操作——矩阵运算
    • 案例6:在遍历列表时删除元素的正确姿势
  • ⚠️ 易错点避坑总结
  • 📝 课后实战练习题
      • 第1题:列表基础操作
      • 第2题:列表方法练习
      • 第3题:购物车系统
      • 第4题:矩阵转置与翻转
      • 第5题:列表推导式高级练习
      • 第6题:深拷贝与浅拷贝实验
      • 第7题:约瑟夫环问题(经典算法)
  • 🔜 下节课预告
    • 第9课:元组Tuple与字典Dict底层原理及实战用法
  • 🔗《50节课 Python 从入门到精通》系列课程导航

📖 开篇导读

前几节课我们学习了字符串——一种存储字符序列的数据类型。但字符串只能存放字符,而且不可变。在实际开发中,我们经常需要处理一组数据:比如一个班级的学生姓名列表、一周的气温记录、待办事项清单……这些数据可能包含不同类型(整数、浮点数、字符串甚至其他列表),并且需要随时增删改查。

这时就需要列表。列表是Python中最灵活、最常用的容器类型,它可以存放任意类型的数据,并且可变(可以随时修改)。几乎任何需要处理“一组数据”的场景,列表都是首选。

💡 工作场景:读取CSV文件的一行数据,存在列表里;爬虫抓取的网页标题列表;数据库查询结果的每一行;用户上传的多个文件路径;机器学习中的特征向量……列表无处不在。

这一课,我们将系统学习列表的所有核心知识点:创建、索引、切片、常用方法、遍历方式、列表推导式、嵌套列表,以及深浅拷贝的区别。学完本课,你将能自如地管理任何集合数据。


🎯 学习目标

目标编号具体掌握内容对应面试/工作价值
1️⃣ 掌握列表的定义、特性(可变、有序、可重复) 理解列表与元组、集合的区别
2️⃣ 熟练使用增删改查方法(append、insert、remove、pop等) 日常数据操作
3️⃣ 掌握列表切片和遍历的多种方式 批量处理数据
4️⃣ 理解列表推导式,能写出简洁高效的代码 面试高频,替代map/filter
5️⃣ 掌握嵌套列表的创建与访问 处理矩阵、表格数据
6️⃣ 区分浅拷贝与深拷贝,理解其底层原理 防止共享引用导致的bug

🔥 面试考点:面试官常问“列表和元组的区别?”“列表的append和extend区别?”“如何在遍历列表时删除元素?”“列表推导式与生成器表达式的区别?”“深浅拷贝的实现方式?”


📚 知识点理论精讲

一、列表的定义与特性

1.1 什么是列表

列表是Python内置的可变序列,用方括号[]表示,元素之间用逗号分隔。

# 空列表
empty = []

# 同类型元素
numbers = [1, 2, 3, 4, 5]
fruits = ["苹果", "香蕉", "橙子"]

# 混合类型(Python允许,但通常不建议)
mixed = [1, "hello", 3.14, True]

# 列表可以嵌套
matrix = [[1, 2], [3, 4]]

🧠 通俗类比:列表就像一个可伸缩的置物架——你可以往上面放任何东西(元素),东西有顺序,可以随时拿掉、替换、增加新的,架子的大小可以动态变化。

1.2 列表的核心特性

特性说明示例
有序 元素有固定的位置,可以通过索引访问 [1,2,3]和[2,1,3]是不同的列表
可变 可以修改、增加、删除元素 lst[0]=100
可重复 元素可以重复出现 [1,1,2]合法
异构 可以存放不同类型的元素 [1, "a"]合法
动态长度 长度可以随时变化 append、pop等

1.3 列表的创建方式

# 方式1:方括号
lst1 = [1, 2, 3]

# 方式2:list()构造器(从可迭代对象创建)
lst2 = list("hello") # ['h','e','l','l','o']
lst3 = list(range(5)) # [0,1,2,3,4]

# 方式3:列表推导式(后面详解)
squares = [x**2 for x in range(10)]

# 方式4:重复运算符
zeros = [0] * 5 # [0,0,0,0,0]


二、列表的常用操作

2.1 访问元素:索引与切片

列表的索引和切片规则与字符串完全相同(正索引、负索引、左闭右开)。

fruits = ["apple", "banana", "cherry", "durian", "elderberry"]

# 索引
print(fruits[0]) # apple
print(fruits[–1]) # elderberry
print(fruits[2]) # cherry

# 切片(返回新列表)
print(fruits[1:4]) # ['banana', 'cherry', 'durian']
print(fruits[:3]) # ['apple', 'banana', 'cherry']
print(fruits[::2]) # ['apple', 'cherry', 'elderberry']
print(fruits[::–1]) # 反转列表

📌 工作应用:切片常用于分页、获取子集。

2.2 修改元素

直接通过索引赋值即可修改。

nums = [10, 20, 30]
nums[1] = 25
print(nums) # [10, 25, 30]

# 切片赋值(可以同时修改多个元素,甚至改变长度)
nums[0:2] = [100, 200, 300] # 替换前两个元素为三个新元素
print(nums) # [100, 200, 300, 30]

2.3 添加元素

方法说明示例
append(x) 在列表末尾添加一个元素 lst.append(4)
insert(i, x) 在索引i处插入元素x lst.insert(0, 'start')
extend(iterable) 将可迭代对象的所有元素追加到末尾 lst.extend([4,5])

tasks = ["写报告", "开会"]

# append:加一个元素
tasks.append("回复邮件")
print(tasks) # ['写报告', '开会', '回复邮件']

# insert:在指定位置插入
tasks.insert(1, "吃午饭")
print(tasks) # ['写报告', '吃午饭', '开会', '回复邮件']

# extend:合并另一个列表
new_tasks = ["检查代码", "提交PR"]
tasks.extend(new_tasks)
print(tasks) # ['写报告', '吃午饭', '开会', '回复邮件', '检查代码', '提交PR']

💡 面试考点:问“append和extend的区别?”答:append将参数作为一个元素添加;extend将可迭代对象的每个元素分别添加。

2.4 删除元素

方法说明返回值
remove(x) 删除第一个值为x的元素,不存在则报错 None
pop(i=-1) 删除并返回索引i处的元素(默认最后一个) 被删除的元素
clear() 清空列表所有元素 None
del lst[i] 删除索引i的元素(或切片) 无(语句)

cart = ["苹果", "香蕉", "橙子", "苹果"]

# remove:按值删除第一个匹配
cart.remove("苹果") # 删除了第一个苹果
print(cart) # ['香蕉', '橙子', '苹果']

# pop:按索引删除并返回
item = cart.pop(1) # 删除索引1的"橙子"
print(item) # 橙子
print(cart) # ['香蕉', '苹果']

cart.pop() # 删除最后一个
print(cart) # ['香蕉']

# clear:清空
cart.clear()
print(cart) # []

# del语句
nums = [1, 2, 3, 4, 5]
del nums[2] # 删除索引2的元素
print(nums) # [1, 2, 4, 5]
del nums[0:2] # 删除切片
print(nums) # [5]

⚠️ 高频坑点:remove删除的是第一个匹配的值,如果要删除所有匹配值,需要循环或列表推导。pop不传参数时删除最后一个,比pop(0)快(因为删除开头需要移动后面所有元素)。

2.5 查询与统计

方法说明返回值
index(x, start, end) 返回第一个x的索引,不存在则报错 int
count(x) 统计x出现的次数 int
len(lst) 返回列表长度 int
x in lst 判断x是否在列表中 bool

scores = [85, 92, 78, 92, 88]

print(scores.index(92)) # 1(第一次出现的位置)
# print(scores.index(100)) # ValueError
print(scores.count(92)) # 2
print(len(scores)) # 5
print(85 in scores) # True
print(100 not in scores) # True

# index可以指定搜索范围
print(scores.index(92, 2)) # 从索引2开始找:返回3

2.6 排序与反转

方法说明注意
list.sort(key=None, reverse=False) 原地排序,修改原列表 返回None
sorted(list, …) 返回新列表,原列表不变 内置函数
list.reverse() 原地反转 返回None
list[::-1] 切片反转,返回新列表 不修改原列表

nums = [3, 1, 4, 1, 5, 9]

# 原地排序(升序)
nums.sort()
print(nums) # [1, 1, 3, 4, 5, 9]

# 降序
nums.sort(reverse=True)
print(nums) # [9, 5, 4, 3, 1, 1]

# 使用sorted返回新列表
original = [3, 2, 1]
sorted_new = sorted(original)
print(original) # [3, 2, 1] 不变
print(sorted_new) # [1, 2, 3]

# 反转
nums = [1, 2, 3]
nums.reverse()
print(nums) # [3, 2, 1]

# 切片反转(不修改原列表)
new_nums = nums[::–1]

💡 工作应用:sort的key参数可以指定排序依据,比如按字符串长度排序:lst.sort(key=len),按第二个元素排序:lst.sort(key=lambda x: x[1])。

2.7 复制列表:浅拷贝与深拷贝

这是列表操作中最容易出错的点之一。

浅拷贝:只复制第一层,内部嵌套的对象还是引用

# 浅拷贝的几种方式
original = [1, 2, [3, 4]]
copy1 = original[:] # 切片
copy2 = list(original) # 构造器
copy3 = original.copy() # copy方法
import copy; copy4 = copy.copy(original) # copy模块

# 修改浅拷贝的外层元素不影响原列表
copy1[0] = 100
print(original[0]) # 1(不变)

# 但是修改内层可变对象会影响原列表
copy1[2][0] = 99
print(original[2]) # [99, 4](被改了!)

深拷贝:递归复制所有层级,完全独立

import copy
original = [1, 2, [3, 4]]
deep = copy.deepcopy(original)

deep[2][0] = 999
print(original[2]) # [3, 4] 不受影响

🔥 面试考点:“列表的浅拷贝和深拷贝区别?如何实现?”答:浅拷贝只复制引用,深拷贝递归复制所有内容。用copy.copy()和copy.deepcopy()。


三、遍历列表的多种方式

3.1 直接遍历元素

fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)

3.2 遍历索引(使用range和len)

for i in range(len(fruits)):
print(f"索引{i}: {fruits[i]}")

3.3 同时遍历索引和元素(enumerate)

for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")

# 可以指定起始索引
for i, fruit in enumerate(fruits, start=1):
print(f"{i}: {fruit}")

3.4 并行遍历多个列表(zip)

names = ["张三", "李四", "王五"]
ages = [25, 30, 28]

for name, age in zip(names, ages):
print(f"{name} {age}岁")

3.5 倒序遍历

for fruit in reversed(fruits):
print(fruit)

# 或者用切片
for fruit in fruits[::–1]:
print(fruit)


四、列表推导式(List Comprehension)

列表推导式是Python独有的函数式编程特性,能够用一行简洁的代码生成新列表。

4.1 基本语法

[表达式 for 变量 in 可迭代对象 if 条件]

4.2 基础示例

# 传统方式
squares = []
for i in range(10):
squares.append(i**2)

# 列表推导式
squares = [i**2 for i in range(10)]

# 带条件:只保留偶数平方
even_squares = [i**2 for i in range(10) if i % 2 == 0]
print(even_squares) # [0, 4, 16, 36, 64]

4.3 嵌套循环的列表推导

# 生成坐标对
coords = [(x, y) for x in range(3) for y in range(2)]
print(coords) # [(0,0),(0,1),(1,0),(1,1),(2,0),(2,1)]

# 等价于:
coords = []
for x in range(3):
for y in range(2):
coords.append((x, y))

4.4 条件表达式(三元)结合

# 对列表中的数字,偶数保留,奇数变为0
nums = [1, 2, 3, 4, 5]
result = [x if x % 2 == 0 else 0 for x in nums]
print(result) # [0, 2, 0, 4, 0]

4.5 列表推导式 vs map/filter

# map: 对每个元素应用函数
nums = [1, 2, 3, 4]
squares_map = list(map(lambda x: x**2, nums))

# 列表推导更可读
squares_comp = [x**2 for x in nums]

# filter: 筛选元素
even_filter = list(filter(lambda x: x % 2 == 0, nums))
even_comp = [x for x in nums if x % 2 == 0]

💡 工作应用:列表推导式简洁、性能通常优于手动循环,但不建议过于复杂(嵌套超过两层或包含复杂逻辑时,还是用普通循环可读性更好)。


五、嵌套列表(多维列表)

列表中的元素可以是列表,形成多维结构。

5.1 创建二维列表

# 3行4列的矩阵(全0)
matrix = [[0 for _ in range(4)] for _ in range(3)]

# 注意:错误的创建方式(共享引用)
bad_matrix = [[0] * 4] * 3 # 三行引用同一个列表!
bad_matrix[0][0] = 1
print(bad_matrix) # [[1,0,0,0], [1,0,0,0], [1,0,0,0]] 一起变了

⚠️ 高频坑点:用[[0]*4]*3创建二维列表时,内层列表是同一个对象的引用,修改一个会影响所有行。正确做法用列表推导:[[0]*4 for _ in range(3)]。

5.2 访问和修改嵌套列表

matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]

print(matrix[0][1]) # 2(第0行第1列)
matrix[1][2] = 100 # 修改第二行第三列
print(matrix) # [[1,2,3],[4,5,100],[7,8,9]]

# 遍历二维列表
for row in matrix:
for elem in row:
print(elem, end=" ")
print()

5.3 应用:矩阵转置

matrix = [[1,2,3], [4,5,6]]
# 转置为3行2列
transpose = [[matrix[j][i] for j in range(len(matrix))] for i in range(len(matrix[0]))]
print(transpose) # [[1,4],[2,5],[3,6]]


六、列表的高级技巧与性能

6.1 使用*重复列表的陷阱

# 对一维列表,元素是不可变类型时没问题
a = [0] * 5 # [0,0,0,0,0]
a[0] = 1 # 独立修改,没问题

# 但如果列表元素是可变对象,则所有元素引用同一个对象
b = [ [0] ] * 3 # [[0], [0], [0]]
b[0][0] = 1
print(b) # [[1],[1],[1]] —— 全部变了

6.2 列表作为栈和队列

  • 栈(LIFO后进先出):append压栈,pop()弹栈。
  • 队列(FIFO先进先出):append入队,pop(0)出队(但效率低,可用collections.deque)。

# 栈
stack = []
stack.append(1)
stack.append(2)
stack.pop() # 2

# 队列(不推荐用列表,效率低)
from collections import deque
q = deque([1,2,3])
q.append(4)
q.popleft() # 1

6.3 列表的内存动态分配

列表是动态数组,当容量不足时,Python会分配更大的内存(通常是当前容量的1.125倍左右),复制元素到新内存。频繁的append会有少量开销,但总体仍是O(1)均摊。


💻 代码案例实操

案例1:待办事项管理器(增删改查综合)

"""
todo_manager.py
一个简单的命令行待办事项管理器,演示列表增删改查
"""

todos = []

def show_menu():
print("\\n===== 待办事项管理器 =====")
print("1. 查看所有待办")
print("2. 添加待办")
print("3. 删除待办")
print("4. 修改待办")
print("5. 退出")

def show_todos():
if not todos:
print("暂无待办事项")
return
print("\\n当前待办列表:")
for i, todo in enumerate(todos, 1):
print(f"{i}. {todo}")

def add_todo():
todo = input("请输入待办内容:").strip()
if todo:
todos.append(todo)
print(f"已添加:{todo}")
else:
print("内容不能为空")

def delete_todo():
show_todos()
if not todos:
return
try:
idx = int(input("请输入要删除的序号:")) – 1
if 0 <= idx < len(todos):
removed = todos.pop(idx)
print(f"已删除:{removed}")
else:
print("序号无效")
except ValueError:
print("请输入数字")

def update_todo():
show_todos()
if not todos:
return
try:
idx = int(input("请输入要修改的序号:")) – 1
if 0 <= idx < len(todos):
new_content = input("请输入新内容:").strip()
if new_content:
old = todos[idx]
todos[idx] = new_content
print(f"已修改:{old} -> {new_content}")
else:
print("内容不能为空")
else:
print("序号无效")
except ValueError:
print("请输入数字")

while True:
show_menu()
choice = input("请选择操作(1-5): ")
if choice == '1':
show_todos()
elif choice == '2':
add_todo()
elif choice == '3':
delete_todo()
elif choice == '4':
update_todo()
elif choice == '5':
print("感谢使用,再见!")
break
else:
print("无效选项,请重新输入")

案例2:列表排序与筛选——学生成绩处理

"""
grade_processor.py
对学生成绩列表进行各种操作
"""

# 原始成绩(姓名,分数)
students = [
("张三", 85),
("李四", 92),
("王五", 78),
("赵六", 60),
("周七", 45)
]

# 1. 按分数升序排序
students_sorted = sorted(students, key=lambda x: x[1])
print("按分数升序:", students_sorted)

# 2. 按分数降序(前三名)
students_desc = sorted(students, key=lambda x: x[1], reverse=True)
top3 = students_desc[:3]
print("前三名:", top3)

# 3. 筛选出及格(>=60)的学生
passed = [s for s in students if s[1] >= 60]
print("及格名单:", passed)

# 4. 计算平均分
avg_score = sum(s[1] for s in students) / len(students)
print(f"平均分: {avg_score:.2f}")

# 5. 找出最高分和最低分
max_student = max(students, key=lambda x: x[1])
min_student = min(students, key=lambda x: x[1])
print(f"最高分: {max_student[0]} ({max_student[1]})")
print(f"最低分: {min_student[0]} ({min_student[1]})")

# 6. 统计各分数段人数
segments = [0, 0, 0, 0, 0] # <60, 60-69, 70-79, 80-89, >=90
for _, score in students:
if score < 60:
segments[0] += 1
elif score < 70:
segments[1] += 1
elif score < 80:
segments[2] += 1
elif score < 90:
segments[3] += 1
else:
segments[4] += 1
print(f"分布: <60:{segments[0]}, 60-69:{segments[1]}, 70-79:{segments[2]}, 80-89:{segments[3]}, ≥90:{segments[4]}")

案例3:列表推导式——数据转换与过滤

"""
list_comprehension_demo.py
列表推导式的多种实战场景
"""

# 1. 提取列表中所有偶数
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = [x for x in nums if x % 2 == 0]
print("偶数:", evens)

# 2. 字符串列表转大写
words = ["hello", "world", "python"]
upper_words = [w.upper() for w in words]
print("大写:", upper_words)

# 3. 扁平化嵌套列表(两层)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flatten = [num for row in matrix for num in row]
print("扁平化:", flatten)

# 4. 过滤掉空字符串
data = ["a", "", "b", None, "c", " "]
clean = [s for s in data if s and s.strip()]
print("非空:", clean)

# 5. 带条件表达式的
numbers = [1, 2, 3, 4, 5]
label = ["偶数" if n % 2 == 0 else "奇数" for n in numbers]
print("标签:", label)

# 6. 使用集合去重(保留顺序)
original = [1, 2, 2, 3, 1, 4]
seen = set()
unique = [x for x in original if not (x in seen or seen.add(x))]
print("去重保留顺序:", unique)

案例4:深浅拷贝深度剖析

"""
shallow_deep_copy.py
演示深浅拷贝的区别及实际影响
"""

import copy

print("=== 浅拷贝演示 ===")
original = [1, 2, [3, 4]]
shallow = original.copy()

print("修改浅拷贝的外层元素(不可变)")
shallow[0] = 100
print(f"original: {original}") # [1, 2, [3, 4]] 不变
print(f"shallow: {shallow}") # [100, 2, [3, 4]]

print("\\n修改浅拷贝的内层列表(可变)")
shallow[2][0] = 999
print(f"original: {original}") # [1, 2, [999, 4]] 被影响!
print(f"shallow: {shallow}") # [100, 2, [999, 4]]

print("\\n=== 深拷贝 ===")
original2 = [1, 2, [3, 4]]
deep = copy.deepcopy(original2)
deep[2][0] = 888
print(f"original2: {original2}") # [1, 2, [3, 4]] 不变
print(f"deep: {deep}") # [1, 2, [888, 4]]

# 实际工作场景:配置数据的独立副本
base_config = {"host": "localhost", "ports": [8000, 8001]}
# 如果不希望函数修改原配置,传入深拷贝
def modify_config(cfg):
cfg["ports"].append(8002)
return cfg

new_config = modify_config(copy.deepcopy(base_config))
print("\\n原配置 ports:", base_config["ports"]) # [8000, 8001]
print("新配置 ports:", new_config["ports"]) # [8000, 8001, 8002]

案例5:嵌套列表操作——矩阵运算

"""
matrix_operations.py
实现矩阵加法、乘法等运算
"""

def create_matrix(rows, cols, init=0):
"""创建指定行列的矩阵(使用列表推导避免共享引用)"""
return [[init for _ in range(cols)] for _ in range(rows)]

def print_matrix(matrix):
for row in matrix:
print(" ".join(f"{x:4}" for x in row))

def matrix_add(A, B):
"""矩阵加法(要求同形)"""
rows, cols = len(A), len(A[0])
result = create_matrix(rows, cols)
for i in range(rows):
for j in range(cols):
result[i][j] = A[i][j] + B[i][j]
return result

def matrix_multiply(A, B):
"""矩阵乘法:A(m×n) * B(n×p) = C(m×p)"""
m, n = len(A), len(A[0])
p = len(B[0])
result = create_matrix(m, p)
for i in range(m):
for j in range(p):
total = 0
for k in range(n):
total += A[i][k] * B[k][j]
result[i][j] = total
return result

# 示例
A = [[1, 2], [3, 4]]
B = [[5, 6], [7, 8]]

print("矩阵 A:")
print_matrix(A)
print("\\n矩阵 B:")
print_matrix(B)

C = matrix_add(A, B)
print("\\nA + B:")
print_matrix(C)

D = matrix_multiply(A, B)
print("\\nA * B:")
print_matrix(D)

案例6:在遍历列表时删除元素的正确姿势

"""
delete_while_iterating.py
演示遍历列表时删除元素的常见错误及正确方法
"""

# 错误示例:遍历时直接删除会导致跳过元素
numbers = [1, 2, 3, 4, 5, 6]
for n in numbers:
if n % 2 == 0:
numbers.remove(n) # 删除偶数
print("错误结果:", numbers) # [1, 3, 5] 看起来对了,但若列表是[1,2,2,3]会出问题

# 正确方法1:遍历副本(切片)
numbers = [1, 2, 3, 4, 5, 6]
for n in numbers[:]:
if n % 2 == 0:
numbers.remove(n)
print("方法1(副本):", numbers)

# 正确方法2:倒序遍历,从后向前删除
numbers = [1, 2, 3, 4, 5, 6]
for i in range(len(numbers)–1, –1, –1):
if numbers[i] % 2 == 0:
del numbers[i]
print("方法2(倒序):", numbers)

# 正确方法3:列表推导式(推荐,创建新列表)
numbers = [1, 2, 3, 4, 5, 6]
numbers = [n for n in numbers if n % 2 != 0]
print("方法3(推导):", numbers)

# 正确方法4:filter函数
numbers = [1, 2, 3, 4, 5, 6]
numbers = list(filter(lambda n: n % 2 != 0, numbers))
print("方法4(filter):", numbers)


⚠️ 易错点避坑总结

序号坑点描述后果解决方案
1 使用[[0]*3]*4创建多维列表 内层列表共享引用,修改一个会变所有 用列表推导[[0]*3 for _ in range(4)]
2 遍历列表时直接删除元素 跳过元素或索引错误 遍历副本、倒序遍历或用列表推导
3 误用append添加多个元素 lst.append([a,b])会添加嵌套列表 用extend或+=
4 浅拷贝后修改内层可变对象影响原列表 意想不到的bug 用深拷贝copy.deepcopy()
5 index找不到元素时未处理异常 程序崩溃 先用in判断或try/except
6 pop(0)频繁使用 时间复杂度O(n),效率低 用collections.deque
7 列表作为函数默认参数 def f(lst=[])多次调用共享列表 默认参数设为None
8 sort和sorted混淆 忘记sorted返回新列表 记住:sort原地,sorted新建
9 remove只删除第一个匹配值 需要删除所有匹配时漏删 用循环或列表推导过滤
10 混淆+和extend +返回新列表,extend修改原列表 根据需求选择

📝 课后实战练习题

第1题:列表基础操作

创建一个包含10个随机整数的列表(范围1-100)。完成:

  • 输出列表中的最大值和最小值及其索引。
  • 计算列表平均值。
  • 将列表中所有偶数替换为0。
  • 删除所有大于80的元素(用推导式)。
  • 第2题:列表方法练习

    已知两个列表:list1 = [1, 2, 3, 4, 5] 和 list2 = [4, 5, 6, 7, 8],写出代码:

  • 找出两个列表中都存在的元素(交集)。
  • 找出只在list1中出现但不在list2中的元素(差集)。
  • 合并两个列表并去重,保持原有顺序(先去重再合并)。
  • 第3题:购物车系统

    模拟一个简单的购物车,要求如下:

    • 初始购物车为空字典(商品名:价格),但请用两个平行列表(names, prices)存储。
    • 提供菜单:添加商品、删除商品、修改数量(价格)、查看购物车、结账(计算总价)。
    • 使用列表的相关方法实现。

    第4题:矩阵转置与翻转

    给定一个二维列表(3×4):

    matrix = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12]
    ]

    要求:

  • 写一个函数实现矩阵转置(行列互换)。
  • 写一个函数实现水平翻转(每行倒序)。
  • 写一个函数实现垂直翻转(行顺序倒置)。
  • 第5题:列表推导式高级练习

    给定列表 words = ["apple", "banana", "cherry", "date", "elderberry", "fig"],使用列表推导式完成:

  • 筛选出长度大于5的单词。
  • 将每个单词首字母大写。
  • 生成一个字典,键为单词,值为单词长度(使用字典推导式)。
  • 找出所有包含字母’e’的单词,并得到其索引(使用enumerate和列表推导)。
  • 第6题:深拷贝与浅拷贝实验

    创建列表 original = [1, [2, 3], [4, 5]],分别进行赋值、浅拷贝、深拷贝三种操作。然后修改original[1][0] = 99,观察三个副本的变化,并解释原因。编写代码验证。

    第7题:约瑟夫环问题(经典算法)

    有n个人围成一圈,从第一个人开始报数,数到m的人出列,然后从下一个人继续报数,直到所有人出列。用列表模拟这个过程,输出出列顺序。例如n=5, m=3,输出应为[3,1,5,2,4]。

    🔜 下节课预告

    列表是可变序列,元组是不可变序列;字典是键值对映射。下节课我们将深入剖析元组和字典。

    第9课:元组Tuple与字典Dict底层原理及实战用法

    内容包括:

    • 元组的定义、特性和不可变性
    • 元组的打包与解包
    • 字典的底层哈希表原理
    • 字典常用操作(增删改查、遍历)
    • 字典推导式
    • 元组与列表的选择场景
    • 实战:词频统计、电话本系统

    元组和字典是Python数据结构的另外两块重要拼图,掌握它们你将能应对更多复杂数据组织需求。

    🌟 学习鼓励:列表是Python中最常用的数据结构,它的灵活性让数据处理变得轻松。但正因为灵活,也容易出错(尤其是浅拷贝和遍历删除)。建议你把文中的案例逐一运行,修改参数观察效果,亲手踩坑才能印象深刻。继续加油!


    🔗《50节课 Python 从入门到精通》系列课程导航

    去订阅

    🌟 感谢您耐心阅读到这里! 💡 如果本文对您有所启发欢迎: 👍 点赞📌 收藏 📤 分享给更多需要的伙伴。 🗣️ 期待在评论区看到您的想法, 共同进步。 🔔 关注我,持续获取更多干货内容~ 🤗 我们下篇文章见~

    赞(0)
    未经允许不得转载:171主机测评 » 第8课:Python|列表List详解【增删改查、遍历与嵌套列表实战】
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址