1. 引言

Python 数据类型与程序结构

数据类型

程序结构

基本类型

容器类型

数字类型
int, float, complex

字符串
str

布尔型
bool

序列类型

映射类型

集合类型

列表 list
有序可变

元组 tuple
有序不可变

字符串 str
有序不可变

字典 dict
键值对映射

集合 set
无序不重复

顺序结构

条件分支
if/elif/else

循环结构

异常处理
try/except

for 循环
遍历序列

while 循环
条件控制

图1:Python数据类型与程序结构概览图 - 展示了本教程涵盖的核心知识点及其关系,帮助你建立整体认知框架。

Python 作为一门简洁、易读且功能强大的编程语言,其核心基础在于对数据类型的理解和程序结构的掌握。无论是进行数据分析、Web 开发还是自动化脚本编写,熟练运用数据类型和控制程序流程都是必备技能。本教程将系统性地介绍 Python 中最常用的几种数据类型,并详细讲解其核心程序结构,辅以丰富的代码示例,帮助初学者快速构建扎实的编程基础。

2. Python 常用数据类型

Python 中的数据类型决定了数据在内存中的存储方式以及可以对其执行的操作。以下是几种最基础且重要的数据类型。

2.1 数字类型 (Numeric Types)

操作示例

整数运算

25 + 10 = 35
25 / 2 = 12.5
25 // 2 = 12

浮点数运算

19.99 * 2 = 39.98
0.1 + 0.2 ≈ 0.30000000000000004

类型转换

int(3.14) → 3
float(25) → 25.0
complex(3, 4) → 3+4j

数字类型内存表示

整数 int
age = 25

内存地址: 0x1000
值: 25
类型: int

浮点数 float
price = 19.99

内存地址: 0x2000
值: 19.99
类型: float

复数 complex
z = 3+4j

内存地址: 0x3000
实部: 3.0
虚部: 4.0
类型: complex

图2:数字类型内存布局与操作示例 - 展示了不同数字类型在内存中的存储方式以及常见操作的结果。

Python 支持整数、浮点数和复数。

知识点讲解:
数字类型是编程中最基础的数据类型。Python 中的数字类型具有以下特点:

  1. 整数 (int):表示没有小数部分的数字,可以是正数、负数或零。Python 3 中的整数没有大小限制(受内存限制)。
  2. 浮点数 (float):表示带有小数部分的数字,使用双精度浮点数实现,精度约为 15 位小数。
  3. 复数 (complex):由实部和虚部组成,形式为 a + bj,其中 a 是实部,b 是虚部,j 表示虚数单位。

代码推导与讲解:

# 整数 (int)
age = 25
count = -10
binary_num = 0b1010  # 二进制表示,相当于十进制的10
print(f"整数 age: {age}, 类型: {type(age)}")
# 讲解:这里展示了整数的三种表示方式:
# 1. 十进制表示:25, -10
# 2. 二进制表示:0b1010(以 0b 开头)
# 3. 使用type()函数可以查看变量的数据类型

# 浮点数 (float)
price = 19.99
pi = 3.1415926
scientific = 2.5e-3  # 科学计数法表示 0.0025
print(f"浮点数 price: {price}, 类型: {type(price)}")
# 讲解:浮点数可以使用小数表示,也可以使用科学计数法表示。
# 科学计数法格式:`数字e指数`,如 2.5e-3 表示 2.5 × 10⁻³ = 0.0025

# 复数 (complex)
complex_num = 3 + 4j
print(f"复数: {complex_num}, 实部: {complex_num.real}, 虚部: {complex_num.imag}")
# 讲解:复数由实部和虚部组成,虚部用 j 表示(不是数学中的 i)。
# 可以通过.real和.imag属性分别获取实部和虚部

易错点总结:

  1. 整数除法:Python 3 中 / 总是返回浮点数,// 才是整数除法
  2. 浮点数精度:浮点数计算可能存在精度误差,如 0.1 + 0.2 != 0.3
  3. 类型转换:使用 int()float()complex() 进行类型转换时要注意数据有效性
  4. 复数表示:虚部必须用 j 而不是 i,且不能单独使用 j(如 4j 是合法的,但 j 不是)

2.2 字符串 (String)

不可变性演示

str1 = 'abc'

str1[0] = 'd'
❌ TypeError

str2 = str1

str2 = 'def'
✅ 创建新对象

字符串操作

原始字符串

切片操作

方法调用

新字符串

'Hello World'

[0:5]

.upper()

'HELLO'

'Python'

[::-1]

.replace('P','J')

'Jython'

字符串内存结构

字符串: 'Hello'

索引: 0 1 2 3 4

字符: H e l l o

内存地址
连续存储

图3:字符串内存结构与操作流程 - 展示了字符串的索引、切片、方法调用过程,以及不可变性的概念。

字符串用于表示文本信息,由单引号 '、双引号 " 或三引号 '''/""" 包裹。

知识点讲解:
字符串是Python中用于处理文本数据的基本数据类型。关键概念包括:

  1. 不可变性:字符串一旦创建就不能修改,所有修改操作都会创建新的字符串。
  2. 索引和切片:可以通过索引访问单个字符,通过切片获取子串。
  3. 常用方法:Python 提供了丰富的字符串方法,用于大小写转换、查找、替换等操作。
  4. 格式化:有多种字符串格式化方式,f-string 是 Python 3.6+ 推荐的方式。

代码推导与讲解:

# 字符串定义
name = "Alice"
greeting = 'Hello, World!'
multiline_str = """这是一个
多行
字符串。"""
# 讲解:Python 支持三种引号定义字符串:
# 1. 单引号:适合简单字符串
# 2. 双引号:适合包含单引号的字符串
# 3. 三引号:适合多行字符串,会保留换行符

# 字符串操作
print(name[0])          # 索引: 'A'
# 讲解:字符串索引从0开始,name[0]获取第一个字符'A'

print(greeting[7:12])   # 切片: 'World'
# 讲解:切片语法 [start:end],包含start,不包含end
# greeting[7:12] 获取第7到第11个字符(索引从0开始)

print(len(name))        # 长度: 5
# 讲解:len()函数返回字符串的字符数(注意:中文字符也按1个字符计算)

print(name.upper())     # 转为大写: 'ALICE'
# 讲解:.upper()方法返回字符串的大写版本,原字符串不变

print("Hello, " + name) # 拼接: 'Hello, Alice'
# 讲解:使用+运算符拼接字符串,效率较低,适合少量拼接

print(f"Hello, {name}") # f-string 格式化 (推荐)
# 讲解:f-string是Python 3.6+引入的格式化方式,在字符串前加f,
# 用{}包裹变量或表达式,代码更简洁,执行效率更高

易错点总结:

  1. 索引越界:访问不存在的索引会引发IndexError
  2. 字符串不可变:不能通过索引修改字符串,如 name[0] = 'B' 会报错
  3. 编码问题:处理中文等非ASCII字符时要注意编码(Python 3默认使用UTF-8)
  4. 转义字符:如 \n(换行)、\t(制表符)、\\(反斜杠)等需要正确使用
  5. 内存效率:大量字符串拼接使用join()比+更高效

2.3 列表 (List)

列表推导式执行过程

原始数据
range(5)

遍历每个元素 x

计算表达式
x**2

收集结果
[0, 1, 4, 9, 16]

列表操作时间复杂度

索引访问
fruits[2]

O(1)
常数时间

末尾添加
fruits.append()

O(1)
平摊常数

中间插入
fruits.insert(1)

O(n)
线性时间

查找元素
'apple' in fruits

O(n)
线性时间

列表内存动态分配

创建列表
fruits = ['apple']

内存: 0x1000
容量: 4
大小: 1

添加元素
fruits.append('banana')

内存: 0x1000
容量: 4
大小: 2

继续添加
fruits.append('cherry')

内存: 0x1000
容量: 4
大小: 3

超出容量
fruits.append('orange')

内存: 0x2000
容量: 8
大小: 4
⚠️ 重新分配

图4:列表内存动态分配与操作复杂度 - 展示了列表的动态扩容机制、不同操作的时间复杂度,以及列表推导式的执行过程。

列表是一个有序、可变的数据结构,可以包含不同类型的元素。

知识点讲解:
列表是Python中最常用的数据结构之一,具有以下特点:

  1. 有序性:元素按插入顺序存储,可以通过索引访问
  2. 可变性:可以添加、删除、修改元素
  3. 异构性:可以包含不同类型的数据
  4. 动态大小:列表大小可以动态调整,无需预先指定长度
  5. 列表推导式:一种简洁创建列表的语法糖

代码推导与讲解:

# 列表定义
fruits = ['apple', 'banana', 'cherry']
mixed_list = [1, 'hello', 3.14, True]
# 讲解:列表用方括号[]定义,元素用逗号分隔
# 列表可以包含任意类型的数据,如mixed_list包含整数、字符串、浮点数、布尔值

# 列表操作
fruits.append('orange')      # 在末尾添加元素
# 讲解:append()方法在列表末尾添加一个元素,时间复杂度O(1)

fruits.insert(1, 'blueberry') # 在索引1处插入
# 讲解:insert(index, element)在指定位置插入元素,后面的元素后移
# 注意:在列表中间插入元素的时间复杂度为O(n)

print(fruits[2])             # 访问: 'cherry'
# 讲解:通过索引访问元素,索引从0开始,负数索引表示从末尾开始

fruits[0] = 'avocado'        # 修改元素
# 讲解:通过索引直接赋值可以修改列表元素

popped = fruits.pop()        # 移除并返回最后一个元素
# 讲解:pop()默认移除最后一个元素,也可以指定索引pop(index)
# 返回被移除的元素,列表长度减1

print(f"列表长度: {len(fruits)}")  # 获取元素个数
# 讲解:len()函数返回列表中元素的数量

print(f"切片: {fruits[1:3]}") # 获取子列表
# 讲解:切片语法 [start:end:step],返回新的列表
# fruits[1:3] 获取索引1到2的元素(不包含索引3)

# 列表推导式 (强大特性)
squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16]
# 讲解:列表推导式是创建列表的简洁方式
# 等价于:
# squares = []
# for x in range(5):
#     squares.append(x**2)
# 推导式更简洁,执行效率也更高

易错点总结:

  1. 浅拷贝与深拷贝:直接赋值是引用,修改会影响原列表;使用 copy()list() 创建浅拷贝
  2. 索引越界:访问不存在的索引会引发 IndexError
  3. 空列表判断:使用 if not my_list: 而不是 if len(my_list) == 0:
  4. 遍历时修改:不要在遍历列表时直接修改列表长度(添加/删除元素),应创建副本或使用列表推导式
  5. 性能考虑:在列表开头插入/删除元素效率低(O(n)),在末尾操作效率高(O(1))

2.4 元组 (Tuple)

元组与列表类似,但它是不可变的。通常用于存储不应被修改的数据集合。

知识点讲解:
元组是不可变的序列类型,具有以下特点:

  1. 不可变性:一旦创建就不能修改,这既是限制也是优势(线程安全、可哈希)
  2. 性能优势:由于不可变,元组比列表更轻量,访问速度通常更快
  3. 可哈希性:元组可以作为字典的键,而列表不能
  4. 解包特性:支持多重赋值和解包操作
  5. 单元素元组:创建单元素元组时必须在元素后加逗号

代码推导与讲解:

# 元组定义
coordinates = (10, 20)
rgb_color = (255, 0, 0)
single_element_tuple = (42,)  # 注意逗号,与 (42) 区分
# 讲解:元组用圆括号 `()` 定义,元素用逗号分隔
# 单元素元组必须加逗号,否则(42)会被解释为整数42

# 元组操作
print(coordinates[0])        # 访问:10
# 讲解:通过索引访问元组元素,语法与列表相同

x, y = coordinates           # 解包
# 讲解:元组解包是将元组元素分别赋值给多个变量
# 等价于:`x = coordinates[0]; y = coordinates[1]`
# 解包时变量数量必须与元组长度一致

print(f"元组长度:{len(rgb_color)}")
# 讲解:`len()` 函数同样适用于元组,返回元素个数

# 元组不可变,以下操作会报错
# coordinates[0] = 100 # TypeError: 'tuple' object does not support item assignment
# 讲解:尝试修改元组元素会引发TypeError
# 这是元组与列表最重要的区别

# 元组的优势示例
point1 = (1, 2)
point2 = (1, 2)
print(point1 == point2)  # True,值相等
print(point1 is point2)  # False,不是同一个对象(但小整数可能会被缓存)

# 元组作为字典键
locations = {
    (40.7128, -74.0060): "New York",
    (51.5074, -0.1278): "London"
}
print(locations[(40.7128, -74.0060)])  # "New York"

易错点总结:

  1. 单元素元组:忘记加逗号,如 t = (1) 创建的是整数而不是元组
  2. 不可变性误解:虽然元组本身不可变,但如果包含可变元素(如列表),这些元素的内容可以修改
  3. 性能误解:元组只在创建时比列表快,访问速度差异很小
  4. 解包错误:解包时变量数量与元组长度不匹配会引发ValueError
  5. 括号可省略:在多数情况下括号可以省略,如 t = 1, 2, 3 也是有效的元组

2.5 字典 (Dictionary)

字典是一种存储键值对映射的无序集合,其键必须是不可变类型(如字符串、数字、元组)。

知识点讲解:
字典是 Python 中非常重要的数据结构,具有以下特点:

  1. 键值对映射:每个键对应一个值,通过键快速访问值。
  2. 无序性:Python 3.7+ 中字典保持插入顺序,但不应依赖顺序进行逻辑判断。
  3. 键的唯一性:字典的键必须是唯一的,重复键会覆盖之前的值。
  4. 键的不可变性:字典的键必须是不可变类型(字符串、数字、元组等)。
  5. 动态大小:字典大小可以动态调整。
  6. 字典推导式:类似列表推导式,用于创建字典。

代码推导与讲解:

# 字典定义
student = {
    "name": "Bob",
    "age": 20,
    "courses": ["Math", "Physics"]
}
# 讲解:字典用花括号 {} 定义,键值对用冒号 : 分隔,不同键值对用逗号分隔。
# 键必须是不可变类型,值可以是任意类型(包括列表、字典等)。

# 字典操作
print(student["name"])               # 访问:'Bob'
# 讲解:通过键访问值,如果键不存在会引发 KeyError。

student["grade"] = "A"               # 添加/修改键值对
# 讲解:如果键不存在则添加,如果键存在则修改对应的值。

print(student.get("hobby", "N/A"))   # 安全获取,键不存在时返回默认值 'N/A'
# 讲解:get(key, default) 方法安全获取值,键不存在时返回默认值而不报错。
# 比直接使用 student["hobby"] 更安全。

# 遍历字典
for key, value in student.items():
    print(f"{key}: {value}")
# 讲解:items() 方法返回键值对的可迭代对象。
# 其他遍历方式:
# - student.keys(): 遍历所有键
# - student.values(): 遍历所有值
# - student.items(): 遍历所有键值对

# 字典推导式
square_dict = {x: x**2 for x in range(5)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# 讲解:字典推导式语法 {key_expression: value_expression for item in iterable}。
# 等价于:
# square_dict = {}
# for x in range(5):
#     square_dict[x] = x**2

# 其他常用操作
# 检查键是否存在
if "name" in student:
    print("name键存在")

# 删除键值对
removed_value = student.pop("age", None)  # 删除age键,返回其值或None
# del student["age"]  # 直接删除,键不存在会报错

# 获取所有键或值
keys = list(student.keys())    # 转换为列表
values = list(student.values())

易错点总结:

  1. 键不存在错误:直接访问不存在的键会引发KeyError,应使用get()方法或先检查
  2. 键的可哈希性:字典的键必须是可哈希的(不可变类型),列表、字典等不能作为键
  3. 字典顺序:Python 3.6之前字典不保证顺序,3.7+保持插入顺序,但逻辑不应依赖顺序
  4. 浅拷贝问题:直接赋值是引用,修改会影响原字典;使用copy()创建浅拷贝
  5. 性能考虑:字典查找时间复杂度为O(1),但内存占用较大
  6. 键的类型:避免使用浮点数作为键(精度问题),可以使用字符串或元组代替

2.6 集合 (Set)

集合是一个由无序且不重复元素构成的数据结构,主要用于成员关系测试和消除重复元素。

# 集合定义
unique_numbers = {1, 2, 3, 3, 4, 4} # 自动去重:{1, 2, 3, 4}
empty_set = set()                    # 注意:不能用 {} 创建空集合,{} 是空字典

# 集合操作
set_a = {1, 2, 3, 4}
set_b = {3, 4, 5, 6}

print(set_a | set_b)   # 并集:{1, 2, 3, 4, 5, 6}
print(set_a & set_b)   # 交集:{3, 4}
print(set_a - set_b)   # 差集(在 a 中但不在 b 中):{1, 2}
print(2 in set_a)      # 成员测试:True

2.6.1 集合操作可视化

集合成员测试效率

列表查找
1000个元素

平均: O(n)
最坏: O(n)

集合查找
1000个元素

平均: O(1)
最坏: O(1)

集合去重过程

原始列表
[1, 2, 2, 3, 3, 3, 4]

转换为集合
set([1, 2, 2, 3, 3, 3, 4])

自动去重
{1, 2, 3, 4}

转换回列表
[1, 2, 3, 4]

集合运算示例

集合 A = {1, 2, 3, 4}

文氏图表示

集合 B = {3, 4, 5, 6}

并集 A | B

交集 A & B

差集 A - B

对称差集 A ^ B

{1, 2, 3, 4, 5, 6}

{3, 4}

{1, 2}

{1, 2, 5, 6}

图5:集合运算可视化与性能对比 - 展示了集合的各种运算结果、去重过程,以及与列表的性能对比。

2.7 数据类型对比与总结

在学习了 Python 的主要数据类型后,让我们通过一个对比表格来总结它们的关键特性,以便在实际编程中根据需求选择最合适的数据结构。

特性 数字类型 (int/float/complex) 字符串 (String) 布尔型 (Boolean) 列表 (List) 元组 (Tuple) 字典 (Dictionary) 集合 (Set)
可变性 ❌ 不可变(数字值不可修改) ❌ 不可变(创建后不能修改) ❌ 不可变(True/False是常量) ✅ 可变(可增删改元素) ❌ 不可变(创建后不能修改) ✅ 可变(可增删改键值对) ✅ 可变(可增删元素)
有序性 ❌ 无序(单个值无顺序概念) ✅ 有序(字符序列保持顺序) ❌ 无序(单个值无顺序概念) ✅ 有序(保持插入顺序) ✅ 有序(保持创建顺序) ⚠️ Python 3.7+ 保持插入顺序,但逻辑不应依赖顺序 ❌ 无序(不保证顺序)
元素要求 整数、浮点数、复数 Unicode字符序列 True 或 False 任意类型,可重复 任意类型,可重复 键:不可变类型(字符串、数字、元组)
值:任意类型
任意可哈希类型,不可重复
主要用途 数学计算、计数、测量 文本处理、格式化输出、数据表示 逻辑判断、条件控制、状态标志 存储有序序列,需要频繁修改的场景 存储不应修改的数据集合,作为字典键,函数返回多个值 键值对映射,快速查找 去重,集合运算(并集、交集、差集)
是否可哈希 ✅ 可哈希(可作为字典键) ✅ 可哈希(可作为字典键) ✅ 可哈希(可作为字典键) ❌ 不可哈希(不能作为字典键) ✅ 可哈希(可作为字典键) ❌ 字典本身不可哈希 ✅ 可哈希(可作为字典键)
语法表示 42, 3.14, 2+3j 'hello', "world", '''multiline''' True, False [元素1, 元素2, ...] (元素1, 元素2, ...) {键1: 值1, 键2: 值2, ...} {元素1, 元素2, ...}
性能特点 运算速度快,内存占用固定 索引O(1),切片O(k),拼接O(n+m) 运算极快,内存占用最小 随机访问 O(1),末尾操作 O(1),中间插入/删除 O(n) 创建和访问比列表稍快,内存占用更小 查找、插入、删除平均 O(1) 成员测试 O(1),集合运算高效
常用方法/操作 +, -, *, /, //, %, ** upper(), lower(), split(), join(), find(), replace() and, or, not, ==, !=, is append(), insert(), pop(), remove(), sort() count(), index() get(), keys(), values(), items(), pop() add(), remove(), union(), intersection(), difference()
典型应用场景 计数器、坐标计算、科学计算、金融计算 用户输入处理、文件读写、日志记录、数据清洗 条件判断、循环控制、函数返回值、状态标记 购物车商品、待办事项、日志记录、数据缓存 坐标点、RGB颜色、数据库记录、函数多返回值 用户信息、配置项、缓存数据、词频统计 去重、权限集合、共同好友、标签系统
内存占用特点 固定大小(int约28字节,float约24字节) 与长度成正比,每个字符约1-4字节 固定大小(约28字节,但通常被优化) 动态分配,预留额外空间(over-allocation) 固定大小,比列表更紧凑 哈希表结构,内存开销较大(存储键值对和哈希) 哈希表结构,只存储键,比字典节省内存
如何根据场景选择合适的数据类型?
  1. 需要存储有序序列且频繁修改列表

    • 适合:购物车商品列表、待办事项、日志记录等需要按顺序处理且可能增删改的场景
    • 示例:tasks = ["写作业", "买菜", "运动"]
  2. 需要存储不应修改的数据或作为字典键元组

    • 适合:坐标点、RGB颜色值、数据库记录、函数返回多个值
    • 示例:point = (10, 20)color = (255, 0, 0)
  3. 需要键值对映射,快速查找字典

    • 适合:用户信息、配置项、缓存数据、词频统计
    • 示例:user = {"name": "张三", "age": 25, "city": "北京"}
  4. 需要去重或集合运算集合

    • 适合:去除列表重复项、查找共同好友、检查元素是否存在
    • 示例:unique_words = set(["apple", "banana", "apple", "orange"])
  5. 需要同时满足多个需求组合使用

    • 列表嵌套字典:students = [{"name": "张三", "score": 85}, {"name": "李四", "score": 92}]
    • 字典值包含列表:course_students = {"数学": ["张三", "李四"], "英语": ["王五"]}
    • 元组作为字典键:locations = {(40.7128, -74.0060): "纽约", (51.5074, -0.1278): "伦敦"}

选择原则总结:

  • 考虑数据是否需要修改:需要修改用列表/字典/集合,不需要修改用元组
  • 考虑访问方式:按位置访问用列表/元组,按键访问用字典,检查存在性用集合
  • 考虑性能需求:大量查找用字典或集合,频繁在末尾增删用列表
  • 考虑数据关系:有关联的键值对用字典,独立元素用列表/集合
  • 考虑内存占用:元组比列表更节省内存,集合比列表去重更高效

掌握这些数据类型的特性和适用场景,能够帮助你在实际编程中做出更合理的选择,写出更高效、更易维护的代码。

3. Python 常见程序结构

条件为真

条件为假

满足循环条件

循环结束

四种结构关系

顺序
基础流程

条件
决策分支

循环
重复执行

异常
错误处理

程序开始执行

顺序结构
代码从上到下逐行执行

条件分支结构
if/elif/else

执行 if 分支

执行 else/elif 分支
或继续后续代码

分支合并点

循环结构
for/while

执行循环体

循环后代码

异常处理结构
try 块

是否发生异常?

执行 except 块
处理异常

执行 else 块
(可选)

执行 finally 块
(可选,总是执行)

程序结束或继续

图6:Python 基本程序结构执行流程图 - 展示了顺序、条件分支、循环和异常处理四种基本程序结构的执行逻辑与关系。顺序结构是默认流程;条件分支根据判断结果选择不同路径;循环结构重复执行直到条件不满足;异常处理则包裹可能出错的代码,确保程序健壮性。

程序结构控制着代码的执行流程,是构建程序逻辑的骨架。

3.1 顺序结构

代码默认从上到下逐行顺序执行。

# 顺序结构示例
print("第一步:准备数据")
data = [1, 2, 3]
print("第二步:处理数据")
total = sum(data)
print("第三步:输出结果")
print(f"总和是: {total}")

3.2 条件分支结构 (if/elif/else)

根据条件判断来决定执行哪部分代码。

# 简单的 if-else
score = 85
if score >= 90:
    grade = 'A'
elif score >= 80:
    grade = 'B'
elif score >= 60:
    grade = 'C'
else:
    grade = 'D'
print(f"分数 {score} 对应的等级是:{grade}")

# 嵌套 if
age = 25
has_permit = True
if age >= 18:
    if has_permit:
        print("可以驾驶。")
    else:
        print("需要考取驾照。")
else:
    print("未成年,不能驾驶。")

3.3 循环结构

用于重复执行某段代码。

3.3.1 for 循环

通常用于遍历序列(如列表、字符串、字典)或执行已知次数的循环。

# 遍历列表
fruits = ['apple', 'banana', 'cherry']
for fruit in fruits:
    print(f"I like {fruit}")

# 使用 range() 函数
for i in range(5):          # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 10, 2):   # 2, 4, 6, 8(起始值,结束值(不含),步长)
    print(i)

# 遍历字典
person = {'name': 'Alice', 'age': 25}
for key in person:          # 遍历键
    print(key)
for value in person.values(): # 遍历值
    print(value)
for key, value in person.items(): # 遍历键值对
    print(f"{key}: {value}")
3.3.2 while 循环

当条件为真时,重复执行代码块。

# 基础 while 循环
count = 0
while count < 5:
    print(f"Count is {count}")
    count += 1  # 重要:必须更新循环条件,否则会陷入无限循环

# 使用 break 和 continue
while True:  # 无限循环结构
    user_input = input("输入 'quit' 退出:")
    if user_input == 'quit':
        print("退出循环。")
        break          # 跳出整个循环
    if user_input == 'skip':
        print("跳过本次循环。")
        continue       # 跳过本次循环的剩余代码,直接进入下一次循环
    print(f"你输入了: {user_input}")

3.4 异常处理结构 (try/except/else/finally)

用于捕获和处理程序在运行时可能出现的错误。

# 基本异常处理
try:
    num = int(input("请输入一个整数: "))
    result = 10 / num
    print(f"10 / {num} = {result}")
except ValueError:
    print("错误:输入的不是有效整数!")
except ZeroDivisionError:
    print("错误:除数不能为零!")
except Exception as e:  # 捕获所有其他异常
    print(f"发生未知错误: {e}")
else:
    print("计算成功完成!")  # 仅在 try 块无异常时执行
finally:
    print("程序执行结束。")  # 无论是否发生异常都会执行

4. 综合示例:学生成绩管理系统 (简易版)

下面我们将数据类型与控制流程结合起来,构建一个简单的命令行学生成绩管理系统。

# 定义一个学生列表,每个学生是一个字典
students = []

def add_student():
    """添加学生信息"""
    name = input("请输入学生姓名: ")
    try:
        score = float(input("请输入学生成绩 (0-100): "))
        if score < 0 or score > 100:
            print("成绩必须在 0-100 之间!")
            return
    except ValueError:
        print("输入无效,请输入数字!")
        return

    student = {"name": name, "score": score}
    students.append(student)
    print(f"学生 {name} 添加成功!")

def show_all_students():
    """显示所有学生信息"""
    if not students:
        print("⚠️  暂无学生信息,请先添加学生。")
        return

    print("\n" + "="*40)
    print("📊 所有学生信息"))
    print("="*40)
    
    # 按成绩从高到低排序显示
    sorted_students = sorted(students, key=lambda x: x['score'], reverse=True)
    
    for idx, stu in enumerate(sorted_students, 1):
        # 计算等级
        score = stu['score']
        if score >= 90:
            grade = 'A'
            grade_desc = '优秀'
        elif score >= 80:
            grade = 'B'
            grade_desc = '良好'
        elif score >= 70:
            grade = 'C'
            grade_desc = '中等'
        elif score >= 60:
            grade = 'D'
            grade_desc = '及格'
        else:
            grade = 'F'
            grade_desc = '不及格'
        
        # 格式化输出
        print(f"{idx:2d}. 姓名: {stu['name']:10s} | 成绩: {score:6.2f} | 等级: {grade} ({grade_desc})")
    
    # 统计信息
    total_students = len(students)
    avg_score = sum(stu['score'] for stu in students) / total_students if total_students > 0 else 0
    max_score = max(stu['score'] for stu in students) if students else 0
    min_score = min(stu['score'] for stu in students) if students else 0
    
    print("-"*40)
   print(f"📈 统计信息: 共 {total_students} 名学生 | 平均分: {avg_score:.2f} | 最高分: {max_score:.2f} | 最低分: {min_score:.2f}")")
    print("="*40 + "\n")

def calculate_average():
    """计算平均成绩"""
    if not students:
      print("⚠️ 暂无学生信息,无法计算平均分。")")
        return

    total_score = sum(stu['score'] for stu in students)
    average = total_score / len(students)
  print(f"📊 平均成绩为: {average:.2f}")}")

def find_student_by_name():
    """根据姓名查找学生"""
    if not students:
        print("⚠️  暂无学生信息,请先添加学生。")
        return
    
    name_to_find = input("请输入要查找的学生姓名 (支持模糊搜索): ").strip()
    
    # 输入验证
    if not name_to_find:
        print("❌  输入不能为空,请重新输入。")
        return
    
    if len(name_to_find) < 2:
        print("⚠️  姓名太短,请输入至少2个字符。")
        choice = input("是否继续搜索?(y/n): ").lower()
        if choice != 'y':
            return
    
    # 模糊搜索(不区分大小写)
    found_students = []
    for stu in students:
        if name_to_find.lower() in stu['name'].lower():
            found_students.append(stu)
    
    if found_students:
        print(f"\n✅  找到 {len(found_students)} 位姓名包含 '{name_to_find}' 的学生:")
        print("-"*50)
        
        # 按成绩排序
        found_students_sorted = sorted(found_students, key=lambda x: x['score'], reverse=True)
        
        for idx, stu in enumerate(found_students_sorted, 1):
            score = stu['score']
            # 计算等级
            if score >= 90:
                grade = 'A'
            elif score >= 80:
                grade = 'B'
            elif score >= 60:
                grade = 'C'
            else:
                grade = 'D'
            
            print(f"{idx:2d}. 姓名: {stu['name']:15s} | 成绩: {score:6.2f} | 等级: {grade}")
            
            # 成绩评价
            if score >= 95:
                print("     评价: 🌟 非常优秀!")
            elif score >= 85:
                print("     评价: 👍 表现良好")
            elif score >= 60:
                print("     评价: 📚 继续努力")
            else:
                print("     评价: 💪 需要加强学习")
            print()
        
        print("-"*50)
        
        # 提供操作建议
        if len(found_students) > 1:
            print("💡  提示: 找到多个学生,请注意区分。")
    else:
        print(f"\n❌  未找到姓名包含 '{name_to_find}' 的学生。")
        print("💡  建议:")
        print("   1. 检查姓名拼写是否正确")
        print("   2. 尝试输入部分姓名进行模糊搜索")
        print("   3. 确认学生是否已添加到系统中")
        
        # 显示所有学生姓名供参考
        if len(students) <= 10:  # 如果学生不多,显示所有姓名
            print("\n📋  当前系统中的学生姓名:")
            all_names = [stu['name'] for stu in students]
            for i in range(0, len(all_names), 5):
                print("   " + ", ".join(all_names[i:i+5]))

# 主程序循环
def main():
    print("🎓 欢迎使用学生成绩管理系统")
    print("="*30)
    
    while True:
        print("\n" + "="*30)
        print("📋 主菜单")
        print("="*30)
        print("1. 添加学生")
        print("2. 显示所有学生")
        print("3. 计算平均成绩")
        print("4. 按姓名查找学生")
        print("5. 退出系统")
        print("="*30)
        
        choice = input("请选择操作 (1-5): ").strip()
        
        if choice == '1':
            add_student()
        elif choice == '2':
            show_all_students()
        elif choice == '3':
            calculate_average()
        elif choice == '4':
            find_student_by_name()
        elif choice == '5':
            print("\n" + "="*30)
            print("👋 感谢使用学生成绩管理系统,再见!")
            print("="*30)
            break
        else:
            print("❌ 无效选择,请输入 1-5 之间的数字!")
            print("💡 提示: 请确保输入的是单个数字,不要包含空格或其他字符。")

# 启动程序
if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n⚠️  检测到程序被中断,正在退出...")
    except Exception as e:
        print(f"\n❌  程序发生意外错误: {e}")
        print("💡  建议: 请检查输入数据是否正确,或联系系统管理员。")
    finally:
        print("程序已结束。")

5. 练习题目

请尝试独立完成

题目 1:数据类型操作
  1. 创建一个列表 numbers,包含 1 到 10 的整数。
  2. 使用列表推导式,生成一个新列表 squared,包含 numbers 中每个元素的平方。
  3. numbers 中筛选出所有偶数,存入新列表 evens
  4. 创建一个字典 student_scores,键为学生姓名(字符串),值为成绩(整数),至少包含 3 条记录。
  5. 计算 student_scores 中所有成绩的平均值。

答案与详细推导:

# 1. 创建包含 1 到 10 整数的列表
numbers = list(range(1, 11))
print(f"numbers列表: {numbers}")
# 推导:range(1, 11) 生成 1 到 10 的整数序列
# 注意:range 的结束值是不包含的,所以 range(1, 11) 生成 1-10

# 2. 使用列表推导式生成平方列表
squared = [x**2 for x in numbers]
print(f"平方列表 squared: {squared}")
# 推导:列表推导式 [x**2 for x in numbers] 遍历 numbers 中的每个元素 x
# 计算 x 的平方 (x**2),并将结果收集到新列表中
# 等价于:
# squared = []
# for x in numbers:
#     squared.append(x**2)

# 3. 筛选偶数到新列表
evens = [x for x in numbers if x % 2 == 0]
print(f"偶数列表 evens: {evens}")
# 推导:列表推导式 [x for x in numbers if x % 2 == 0] 包含条件判断
# x % 2 == 0 检查 x 是否为偶数(除以 2 的余数为 0)
# 只有满足条件的元素才会被收集到新列表中

# 4. 创建学生成绩字典
student_scores = {
    "张三": 85,
    "李四": 92,
    "王五": 78,
    "赵六": 88
}
print(f"学生成绩字典: {student_scores}")
# 推导:字典用花括号 {} 定义,键值对用冒号 : 分隔
# 键是学生姓名(字符串),值是成绩(整数)
# 字典可以包含任意数量的键值对

# 5. 计算平均成绩
total_score = sum(student_scores.values())
average_score = total_score / len(student_scores)
print(f"总成绩: {total_score}, 学生人数: {len(student_scores)}")
print(f"平均成绩: {average_score:.2f}")
# 推导:
# 1. student_scores.values() 返回所有成绩的视图
# 2. sum() 函数计算所有成绩的总和
# 3. len(student_scores) 获取字典中键值对的数量(学生人数)
# 4. 平均值 = 总成绩 / 学生人数
# 5. :.2f 格式化输出,保留两位小数

# 启发性思考问题:
# 1. 如果 numbers 列表包含负数,平方列表会有什么变化?
# 2. 如何修改列表推导式,只保留大于 5 的偶数的平方?
# 3. 如果学生成绩字典中有同名的学生,会发生什么?如何避免?
# 4. 如果某个学生的成绩是字符串类型(如 "85"),计算平均值时会遇到什么问题?如何解决?

题目 2:程序流程控制

  1. FizzBuzz 问题:编写程序,打印 1 到 100 的数字。对于 3 的倍数,打印 “Fizz” 代替数字;对于 5 的倍数,打印 “Buzz”;对于同时是 3 和 5 的倍数,打印 “FizzBuzz”。
  2. 素数判断:编写一个函数 is_prime(n),判断输入的正整数 n 是否为素数(质数)。要求在函数中使用循环实现。
  3. 简单计算器:编写一个程序,让用户输入两个数字和一个运算符(+、-、*、/),根据运算符输出计算结果。要求使用 if-elif-else 结构判断运算符,并处理除零错误。

答案与详细推导:

# 1. FizzBuzz问题
print("=== FizzBuzz问题解答 ===")
for i in range(1, 101):
    if i % 3 == 0 and i % 5 == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        print(i)
# 推导:
# 1. range(1, 101) 生成 1 到 100 的整数
# 2. 先检查同时是 3 和 5 的倍数(即 15 的倍数),因为如果先检查 3 的倍数,15 会被错误地打印为 "Fizz"
# 3. i % 3 == 0 检查 i 是否能被 3 整除(余数为 0)
# 4. i % 5 == 0 检查 i 是否能被 5 整除
# 5. 注意条件的顺序:必须先检查最特殊的情况(同时是 3 和 5 的倍数)

# 2. 素数判断函数
def is_prime(n):
    """判断一个正整数是否为素数"""
    if n <= 1:
        return False  # 1和负数不是素数
    if n == 2:
        return True   # 2是唯一的偶素数
    
    # 检查从2到√n的整数是否能整除n
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            return False  # 找到因子,不是素数
    return True  # 没有找到因子,是素数

# 测试素数判断函数
test_numbers = [2, 3, 4, 17, 25, 29]
for num in test_numbers:
    result = "是素数" if is_prime(num) else "不是素数"
    print(f"{num} {result}")
# 推导:
# 1. 素数定义:大于1的自然数,除了1和它本身以外不再有其他因数
# 2. 优化:只需要检查到√n,因为如果n有因子,必有一个小于等于√n
# 3. n**0.5计算平方根,int()取整,+1确保包含边界
# 4. 特殊处理:1不是素数,2是素数

# 3. 简单计算器
def simple_calculator():
    """简单计算器程序"""
    try:
        # 获取用户输入
        num1 = float(input("请输入第一个数字: "))
        num2 = float(input("请输入第二个数字: "))
        operator = input("请输入运算符 (+, -, *, /): ").strip()
        
        # 根据运算符进行计算
        if operator == '+':
            result = num1 + num2
            print(f"{num1} + {num2} = {result}")
        elif operator == '-':
            result = num1 - num2
            print(f"{num1} - {num2} = {result}")
        elif operator == '*':
            result = num1 * num2
            print(f"{num1} * {num2} = {result}")
        elif operator == '/':
            if num2 == 0:
                print("错误:除数不能为零!")
            else:
                result = num1 / num2
                print(f"{num1} / {num2} = {result:.2f}")  # 保留两位小数
        else:
            print("错误:不支持的运算符!请使用 +, -, *, /")
    
    except ValueError:
        print("错误:请输入有效的数字!")
    except Exception as e:
        print(f"发生未知错误: {e}")

# 测试计算器
print("\n=== 简单计算器测试 ===")
# 取消下面的注释来测试计算器
# simple_calculator()

# 启发性思考问题:
# 1. FizzBuzz问题中,如果要求同时是3和5的倍数打印"FizzBuzz",但是3的倍数打印"Three",5的倍数打印"Five",该如何修改?
# 2. 素数判断函数中,为什么只需要检查到√n?如果n=100,需要检查哪些数字?
# 3. 如何优化素数判断函数的性能?提示:偶数除了2都不是素数
# 4. 计算器程序中,如果用户输入的不是数字,程序会如何处理?如何改进错误提示?
# 5. 如何扩展计算器程序,使其支持更多运算符(如求余%、幂运算**)?

6. 进一步学习资源

恭喜你完成了 Python 常用数据类型和程序结构的学习!为了帮助你继续前进,这里提供一些进一步学习的建议和资源:

1. 官方文档与教程

  • Python 官方文档:最权威的学习资源,包含完整的语言参考和标准库文档。建议从 Python 教程 开始。
  • Python 官方教程中文版:如果你更喜欢中文资料,可以访问 Python 中文官方文档

2. 练习平台与实战项目

  • LeetCode:从简单难度开始,练习算法和数据结构题目。推荐题目:
    • 两数之和(熟悉字典使用)
    • 反转字符串(练习字符串操作)
    • 合并两个有序列表(练习列表操作)
  • Codewars:通过小任务(Kata)提升编程技能,题目按难度分级。
  • 个人小项目
    • 待办事项管理器(使用列表和字典)
    • 简易计算器(巩固条件分支和异常处理)
    • 学生成绩管理系统增强版(尝试添加更多功能)

3. 相关技术栈入门

  • 数据分析与科学计算

    • NumPy:Python 科学计算的基础库,处理多维数组和矩阵运算。
    • Pandas:数据处理和分析的强大工具,特别适合表格数据操作。
    • Matplotlib:数据可视化库,创建各种静态、动态图表。
  • Web 开发

    • Flask:轻量级 Web 框架,适合初学者快速上手 Web 开发。
    • Django:功能全面的 Web 框架,适合构建中大型 Web 应用。
    • FastAPI:现代、高性能的 Web 框架,适合构建 API 服务。
  • 自动化与脚本

    • 文件批量处理:使用 osshutil 模块自动化文件操作。
    • 网络请求:学习 requests 库进行 HTTP 请求和数据抓取。
    • 定时任务:使用 scheduleAPScheduler 库创建定时任务。

4. 学习建议

  1. 动手实践:编程是实践技能,多写代码比只看教程更有效。
  2. 阅读优秀代码:在 GitHub 上查看开源项目的代码,学习别人的编程风格和技巧。
  3. 参与社区:加入 Python 相关论坛(如 Stack Overflow、Reddit 的 r/learnpython)、QQ 群或微信群,提问和解答问题。
  4. 定期复习:每隔一段时间回顾已学知识,尝试用不同的方法解决同一问题。
  5. 构建作品集:将你的项目代码整理到 GitHub,这既是学习记录,也是未来求职的加分项。

记住,学习编程是一个循序渐进的过程。不要急于求成,每天坚持学习和练习,你会逐渐掌握 Python 编程的精髓。祝你学习顺利!
(1, 11)生成1-10

2. 使用列表推导式生成平方列表

squared = [x2 for x in numbers]
print(f"平方列表square# 推导:列表推导式 [x
2 for x in numbers] 遍历 numbers 中的每个元素 x历# 计算 x 的平方 (x**2),并将结果收集到新列表中*2),并将结果收集到新列表中

等价于:

squared = []

for x in numbers:

squared.append(x**2)

3. 筛选偶数到新列表

evens = [x for x in numbers if x % 2 == 0]
print(f"偶数列表evens: {evens}")

推导:列表推导式[x for x in numbers if x % 2 == 0]包含条件判断

x % 2 == 0 检查x是否为偶数(除以2的余数为0)

只有满足条件的元素才会被收集到新列表中

4. 创建学生成绩字典

student_scores = {
“张三”: 85,
“李四”: 92,
“王五”: 78,
“赵六”: 88
}
print(f"学生成绩字典: {student_scores}")

推导:字典用花括号{}定义,键值对用冒号:分隔

键是学生姓名(字符串),值是成绩(整数)

字典可以包含任意数量的键值对

5. 计算平均成绩

total_score = sum(student_scores.values())
average_score = total_score / len(student_scores)
print(f"总成绩: {total_score}, 学生人数: {len(student_scores)}“)
print(f"平均成绩: {average_score:.2f}”)

推导:

1. student_scores.values()返回所有成绩的视图

2. sum()函数计算所有成绩的总和

3. len(student_scores)获取字典中键值对的数量(学生人数)

4. 平均值 = 总成绩 / 学生人数

5. :.2f格式化输出,保留两位小数

启发性思考问题:

1. 如果numbers列表包含负数,平方列表会有什么变化?

2. 如何修改列表推导式,只保留大于5的偶数的平方?

3. 如果学生成绩字典中有同名的学生,会发生什么?如何避免?

4. 如果某个学生的成绩是字符串类型(如"85"),计算平均值时会遇到什么问题?如何解决?


### 题目 2:程序流程控制

1.  **FizzBuzz 问题**:编写程序,打印 1 到 100 的数字。对于 3 的倍数,打印 "Fizz" 代替数字;对于 5 的倍数,打印 "Buzz";对于同时是 3 和 5 的倍数,打印 "FizzBuzz"。
2.  **素数判断**:编写一个函数 `is_prime(n)`,判断输入的正整数 `n` 是否为素数(质数)。要求在函数中使用循环实现。
3.  **简单计算器**:编写一个程序,让用户输入两个数字和一个运算符(+、-、*、/),根据运算符输出计算结果。要求使用 `if-elif-else` 结构判**答案与详细推导**。

**答案与详细推导:**

```python
# 1. FizzBuzz问题
print("=== FizzBuzz问题解答 ===")
for i in range(1, 101):
    if i % 3 == 0 and i % 5 == 0:
        print("FizzBuzz")
    elif i % 3 == 0:
        print("Fizz")
    elif i % 5 == 0:
        print("Buzz")
    else:
        # 1. range(1, 101) 生成 1 到 100 的整数 # 2. 先检查同时是 3 和 5 的倍数(即 15 的倍数),因为如果先检查 3 的倍数,15 会被错误地打印为 "Fizz"5# 3. i % 3 == 0 检查 i 是否能被 3 整除(余数为 0)查# 4. i % 5 == 0 检查 i 是否能被 5 整除== 0 检查i是否能被5整除
# 5. 注意条件的顺序:必须先检查最特殊的情况(同时是3和5的倍数)

# 2. 素数判断函数
def is_prime(n):
    """判断一个正整数是否为素数"""
    if n <= 1:
        return False  # 1和负数不是素数
    if n == 2:
        return True   # 2是唯一的偶素数
    
    # 检查从2到√n的整数是否能整除n
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            return False  # 找到因子,不是素数
    return True  # 没有找到因子,是素数

# 测试素数判断函数
test_numbers = [2, 3, 4, 17, 25, 29]
for num in test_numbers:
    result = "是素数" if is_prime(num) else "不是素数"
    print(f"{num} {result}")
# 推导:
# 1. 素数定义:大于1的自然数,除了1和它本身以外不再有其他因数
# 2. 优化:只需要检查到√n,因为如果n有因子,必有一个小于等于√n
# 3. n**0.5计算平方根,int()取整,+1确保包含边界
# 4. 特殊处理:1不是素数,2是素数

# 3. 简单计算器
def simple_calculator():
    """简单计算器程序"""
    try:
        # 获取用户输入
        num1 = float(input("请输入第一个数字: "))
        num2 = float(input("请输入第二个数字: "))
        operator = input("请输入运算符 (+, -, *, /): ").strip()
        
        # 根据运算符进行计算
        if operator == '+':
            result = num1 + num2
            print(f"{num1} + {num2} = {result}")
        elif operator == '-':
            result = num1 - num2
            print(f"{num1} - {num2} = {result}")
        elif operator == '*':
            result = num1 * num2
            print(f"{num1} * {num2} = {result}")
        elif operator == '/':
            if num2 == 0:
                print("错误:除数不能为零!")
            else:
                result = num1 / num2
                print(f"{num1} / {num2} = {result:.2f}")  # 保留两位小数
        else:
            print("错误:不支持的运算符!请使用 +, -, *, /")
    
    except ValueError:
        print("错误:请输入有效的数字!")
    except Exception as e:
        print(f"发生未知错误: {e}")

# 测试计算器
print("\n=== 简单计算器测试 ===")
# 取消下面的注释来测试计算器
# simple_calculator()

# 启发性思考问题:
# 1. FizzBuzz问题中,如果要求同时是3和5的倍数打印"FizzBuzz",但是3的倍数打印"Three",5的倍数打印"Five",该如何修改?
# 2. 素数判断函数中,为什么只需要检查到√n?如果n=100,需要检查哪些数字?
# 3. 如何优化素数判断函数的性能?提示:偶数除了2都不是素数
# 4. 计算器程序中,如果用户输入的不是数字,程序会如何处理?如何改进错误提示?
# 5. 如何扩展计算器程序,使其支持更多运算符(如求余%、幂运算**)?

题目 3:综合应用

仿照第 4 节的"学生成绩管理系统",尝试为其增加以下功能:

  1. 删除学生:根据学生姓名删除对应的记录。
  2. 成绩排序:实现按成绩从高到低显示所有学生信息的功能。
  3. 数据持久化(进阶):尝试使用 json 模块,将 students 列表保存到文件 students.json 中,并在程序启动时从文件加载数据。

答案与详细推导:

import json
import os

# 全局变量
students = []
DATA_FILE = "students.json"

def load_students():
    """从文件加载学生数据"""
    global students
    if os.path.exists(DATA_FILE):
        try:
            with open(DATA_FILE, 'r', encoding='utf-8') as f:
                students = json.load(f)
            print(f"✅ 已从 {DATA_FILE} 加载 {len(students)} 名学生数据")
        except (json.JSONDecodeError, IOError) as e:
            print(f"⚠️  加载数据失败: {e},将使用空列表")
            students = []
    else:
        print(f"📁 数据文件 {DATA_FILE} 不存在,将创建新文件")
        students = []

def save_students():
    """保存学生数据到文件"""
    try:
        with open(DATA_FILE, 'w', encoding='utf-8') as f:
            json.dump(students, f, ensure_ascii=False, indent=2)
        print(f"✅ 学生数据已保存到 {DATA_FILE}")
    except IOError as e:
        print(f"❌ 保存数据失败: {e}")

def delete_student():
    """根据姓名删除学生"""
    if not students:
        print("⚠️  暂无学生信息,无法删除。")
        return
    
    name_to_delete = input("请输入要删除的学生姓名: ").strip()
    if not name_to_delete:
        print("❌ 姓名不能为空!")
        return
    
    # 查找要删除的学生
    students_to_delete = []
    for i, student in enumerate(students):
        if student['name'] == name_to_delete:
            students_to_delete.append((i, student))
    
    if not students_to_delete:
        print(f"❌ 未找到名为 '{name_to_delete}' 的学生。")
        return
    
    if len(students_to_delete) == 1:
        # 只有一个匹配的学生,直接删除
        index, student = students_to_delete[0]
        deleted_student = students.pop(index)
        print(f"✅ 已删除学生: {deleted_student['name']},成绩: {deleted_student['score']}")
        save_students()
    else:
        # 多个同名学生,让用户选择
        print(f"🔍 找到 {len(students_to_delete)} 位名为 '{name_to_delete}' 的学生:")
        for idx, (index, student) in enumerate(students_to_delete, 1):
            print(f"  {idx}. 成绩: {student['score']}")
        
        try:
            choice = int(input("请选择要删除的学生编号 (输入0取消): "))
            if choice == 0:
                print("操作已取消。")
                return
            elif 1 <= choice <= len(students_to_delete):
                index, student = students_to_delete[choice-1]
                deleted_student = students.pop(index)
                print(f"✅ 已删除学生: {deleted_student['name']},成绩: {deleted_student['score']}")
                save_students()
            else:
                print("❌ 无效的选择!")
        except ValueError:
            print("❌ 请输入有效的数字!")

def show_sorted_students():
    """按成绩从高到低显示学生信息"""
    if not students:
        print("⚠️  暂无学生信息。")
        return
    
    # 使用sorted函数排序,reverse=True表示降序
    sorted_students = sorted(students, key=lambda x: x['score'], reverse=True)
    
    print("\n" + "="*50)
    print("📊 学生成绩排名(从高到低)")
    print("="*50)
    
    for rank, student in enumerate(sorted_students, 1):
        score = student['score']
        # 根据成绩给出评级
        if score >= 90:
            grade = "A (优秀)"
        elif score >= 80:
            grade = "B (良好)"
        elif score >= 70:
            grade = "C (中等)"
        elif score >= 60:
            grade = "D (及格)"
        else:
            grade = "F (不及格)"
        
        # 计算与平均分的差距
        avg_score = sum(s['score'] for s in students) / len(students)
        diff = score - avg_score
        diff_symbol = "↑" if diff > 0 else "↓" if diff < 0 else "="
        
        print(f"{rank:2d}. {student['name']:10s} | 成绩: {score:6.2f} | 等级: {grade:12s} | 与平均分差距: {diff:+.2f} {diff_symbol}")
    
    # 显示统计信息
    print("-"*50)
    total = len(students)
    avg = sum(s['score'] for s in students) / total
    max_score = max(s['score'] for s in students)
    min_score = min(s['score'] for s in students)
    
    print(f"📈 统计: 共{total}人 | 平均分: {avg:.2f} | 最高分: {max_score:.2f} | 最低分: {min_score:.2f}")
    print("="*50)

# 修改主菜单,添加新功能
def enhanced_main_menu():
    """增强版主菜单"""
    load_students()  # 启动时加载数据
    
    while True:
        print("\n" + "="*40)
        print("🎓 增强版学生成绩管理系统")
        print("="*40)
        print("1. 添加学生")
        print("2. 显示所有学生")
        print("3. 按成绩排序显示")
        print("4. 计算平均成绩")
        print("5. 按姓名查找学生")
        print("6. 删除学生")
        print("7. 保存数据")
        print("8. 退出系统")
        print("="*40)
        
        choice = input("请选择操作 (1-8): ").strip()
        
        if choice == '1':
            # 这里可以调用原来的add_student函数
            print("添加学生功能(需实现)")
        elif choice == '2':
            # 这里可以调用原来的show_all_students函数
            print("显示所有学生功能(需实现)")
        elif choice == '3':
            show_sorted_students()
        elif choice == '4':
            # 这里可以调用原来的calculate_average函数
            print("计算平均成绩功能(需实现)")
        elif choice == '5':
            # 这里可以调用原来的find_student_by_name函数
            print("查找学生功能(需实现)")
        elif choice == '6':
            delete_student()
        elif choice == '7':
            save_students()
        elif choice == '8':
            # 退出前询问是否保存
            save_choice = input("退出前是否保存数据?(y/n): ").lower()
            if save_choice == 'y':
                save_students()
            print("👋 感谢使用,再见!")
            break
        else:
            print("❌ 无效选择,请输入 1-8 之间的数字!")

# 启发性思考问题:
# 1. 删除学生功能中,如果有多个同名学生,如何让用户选择要删除的具体是哪一个?
# 2. 成绩排序显示时,如果成绩相同,如何进一步按姓名排序?
# 3. JSON文件中保存了学生数据,如果程序异常退出,数据会丢失吗?如何改进?
# 4. 如何为系统添加"修改学生信息"的功能?
# 5. 如果学生数量很大(如10000人),排序和查找功能可能会变慢,如何优化?
# 6. 如何添加数据备份功能,防止误删或数据损坏?

# 注意:为了保持代码简洁,这里只实现了新增功能
# 实际使用时,需要将原来的add_student、show_all_students等函数整合进来

综合应用提示:

  1. 删除学生:注意处理同名学生的情况,提供选择机制
  2. 成绩排序:使用sorted()函数的key参数和reverse=True实现降序排序
  3. 数据持久化:使用json模块的dump()load()函数,注意异常处理
  4. **用户体验*5. 代码组织:将相关功能模块化,提高代码可维护性。提高代码可维护性程序启动时从文件加载数据。

提示:完成练习时,多使用 print() 函数输出中间结果,帮助调试和理解程序结构。遇到问题,可以回顾教程中的相关示例。

更多推荐