课程 11:列表(List)

🎯 学习目标

1. 核心概念

1.1 什么是列表?

列表(List)是Python中最常用的数据结构之一,用于存储一组有序的数据。列表具有以下重要特性:

💡 重要提示:列表用方括号 [] 表示,元素之间用逗号分隔。索引从0开始计数。

1.2 列表的定义与访问


# 定义列表
nums = [1, 2, 3, 4, 5]
words = ["apple", "banana", "cherry"]
mixed = [1, "hello", True, 3.14, [1, 2, 3]]

# 访问元素(索引从0开始)
print(nums[0])      # 1
print(words[2])     # cherry
print(mixed[-1])    # [1, 2, 3] (最后一个元素)

# 切片访问
print(nums[1:4])    # [2, 3, 4]
print(nums[::2])    # [1, 3, 5] (步长为2)
    

2. 技术实现

2.1 列表的基本操作

Python列表提供了丰富的内置方法来操作数据:

🔧 核心操作方法:

# 列表操作示例
fruits = ["apple", "banana"]
print(f"原始列表: {fruits}")

# 添加元素
fruits.append("cherry")
fruits.insert(1, "orange")
fruits.extend(["grape", "mango"])
print(f"添加后: {fruits}")

# 删除元素
removed = fruits.pop()      # 删除并返回最后一个元素
fruits.remove("orange")     # 删除指定元素
print(f"删除后: {fruits}")
print(f"被删除的元素: {removed}")

# 获取信息
print(f"列表长度: {len(fruits)}")
print(f"是否包含'banana': {'banana' in fruits}")
    

2.2 切片与遍历

列表切片和遍历是处理数据的重要技巧:

📚 切片语法:list[start:end:step],其中start是起始索引,end是结束索引(不包含),step是步长。

# 切片操作详解
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 基本切片
print(numbers[2:5])    # [2, 3, 4] (索引2到4)
print(numbers[:3])     # [0, 1, 2] (从开始到索引2)
print(numbers[7:])     # [7, 8, 9] (从索引7到结束)

# 步长切片
print(numbers[::2])    # [0, 2, 4, 6, 8] (偶数索引)
print(numbers[1::2])   # [1, 3, 5, 7, 9] (奇数索引)
print(numbers[::-1])   # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (反转)

# 负索引切片
print(numbers[-3:])    # [7, 8, 9] (最后3个元素)
print(numbers[:-2])    # [0, 1, 2, 3, 4, 5, 6, 7] (除了最后2个)

# 遍历方式
print("方式1:直接遍历元素")
for num in numbers:
    print(num, end=" ")
print()

print("方式2:遍历索引和元素")
for i, num in enumerate(numbers):
    print(f"索引{i}: {num}")

print("方式3:遍历索引")
for i in range(len(numbers)):
    print(f"位置{i}: {numbers[i]}")
    

2.3 列表推导式

列表推导式是Python的优雅特性,可以用简洁的语法快速生成列表:

🎯 推导式语法:[expression for item in iterable if condition]

# 列表推导式示例

# 基础推导式:生成1-10的平方
squares = [x**2 for x in range(1, 11)]
print(f"平方数: {squares}")

# 条件推导式:筛选偶数
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = [x for x in numbers if x % 2 == 0]
print(f"偶数: {evens}")

# 复杂推导式:字符串处理
words = ["hello", "world", "python", "programming"]
upper_words = [word.upper() for word in words if len(word) > 5]
print(f"长单词转大写: {upper_words}")

# 嵌套推导式:二维列表转一维
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(f"展平矩阵: {flattened}")

# 条件表达式推导式
result = [x if x > 0 else -x for x in [-1, 2, -3, 4, -5]]
print(f"绝对值: {result}")

# 字典推导式(扩展知识)
word_lengths = {word: len(word) for word in words}
print(f"单词长度字典: {word_lengths}")
    

2.4 嵌套列表与多维结构

列表可以嵌套,形成二维、三维甚至更高维的数据结构:

🔍 多维列表应用:常用于表示矩阵、表格数据、图像像素、游戏地图等结构化数据。

# 嵌套列表示例

# 二维列表(矩阵)
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

print("矩阵:")
for row in matrix:
    print(row)

print(f"元素[1][2]: {matrix[1][2]}")  # 6

# 创建3x3单位矩阵
def create_identity_matrix(n):
    return [[1 if i == j else 0 for j in range(n)] for i in range(n)]

identity = create_identity_matrix(3)
print("单位矩阵:")
for row in identity:
    print(row)

# 三维列表(立方体)
cube = [
    [[1, 2], [3, 4]],
    [[5, 6], [7, 8]]
]

print(f"立方体[0][1][0]: {cube[0][1][0]}")  # 3

# 不规则嵌套列表
irregular = [
    [1, 2, 3],
    [4, 5],
    [6, 7, 8, 9],
    [10]
]

print("不规则列表:")
for i, row in enumerate(irregular):
    print(f"行{i}: {row} (长度: {len(row)})")
    

2.5 内置函数与高级操作

Python提供了许多内置函数来简化列表操作:

🚀 常用内置函数:

# 内置函数示例

# 数值计算
numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
print(f"原始列表: {numbers}")
print(f"总和: {sum(numbers)}")
print(f"最大值: {max(numbers)}")
print(f"最小值: {min(numbers)}")
print(f"平均值: {sum(numbers) / len(numbers):.2f}")

# 排序和反转
print(f"升序排序: {sorted(numbers)}")
print(f"降序排序: {sorted(numbers, reverse=True)}")
print(f"反转: {list(reversed(numbers))}")

# 条件检查
print(f"是否所有数都大于0: {all(x > 0 for x in numbers)}")
print(f"是否有数大于8: {any(x > 8 for x in numbers)}")

# 高级排序
students = [
    {"name": "Alice", "age": 20, "grade": 85},
    {"name": "Bob", "age": 19, "grade": 92},
    {"name": "Charlie", "age": 21, "grade": 78}
]

# 按成绩排序
by_grade = sorted(students, key=lambda x: x["grade"], reverse=True)
print("按成绩排序:")
for student in by_grade:
    print(f"{student['name']}: {student['grade']}")

# 按年龄排序
by_age = sorted(students, key=lambda x: x["age"])
print("按年龄排序:")
for student in by_age:
    print(f"{student['name']}: {student['age']}岁")
    

3. 关键知识点详解

3.1 列表基础特性

理解列表的核心特性对于正确使用Python列表至关重要:

🔑 核心特性总结:

# 基础特性示例
lst = [1, "hello", True, [2, 3]]
print(f"原始列表: {lst}")
print(f"列表类型: {type(lst)}")
print(f"列表长度: {len(lst)}")

# 可变性演示
print("\n=== 可变性演示 ===")
original_id = id(lst)
lst[0] = 100
lst.append("new_item")
print(f"修改后: {lst}")
print(f"内存地址变化: {id(lst) == original_id}")  # True

# 有序性演示
print("\n=== 有序性演示 ===")
print(f"第一个元素: {lst[0]}")
print(f"最后一个元素: {lst[-1]}")
print(f"切片[1:3]: {lst[1:3]}")
print(f"步长切片[::2]: {lst[::2]}")

# 元素多样性演示
print("\n=== 元素多样性演示 ===")
for i, item in enumerate(lst):
    print(f"索引{i}: {item} (类型: {type(item)})")
    

3.2 列表元素的增删改

列表的增删改操作是日常编程中最常用的功能:

➕ 增加元素方法:

# 增加元素示例
fruits = ["apple"]
print(f"初始列表: {fruits}")

# 添加单个元素
fruits.append("banana")
print(f"append后: {fruits}")

# 插入元素
fruits.insert(1, "orange")
print(f"insert后: {fruits}")

# 扩展列表
fruits.extend(["cherry", "date", "elderberry"])
print(f"extend后: {fruits}")

# 使用+=操作符
fruits += ["fig", "grape"]
print(f"+=操作后: {fruits}")

# 在指定位置插入多个元素
fruits[2:2] = ["kiwi", "lemon"]
print(f"切片插入后: {fruits}")
    
➖ 删除元素方法:

# 删除元素示例
numbers = [1, 2, 3, 2, 4, 5, 2, 6]
print(f"原始列表: {numbers}")

# 删除指定值
numbers.remove(2)  # 只删除第一个2
print(f"remove(2)后: {numbers}")

# 弹出元素
popped = numbers.pop()      # 删除并返回最后一个元素
print(f"pop()后: {numbers}")
print(f"被弹出的元素: {popped}")

popped_index = numbers.pop(1)  # 删除索引1的元素
print(f"pop(1)后: {numbers}")
print(f"被弹出的元素: {popped_index}")

# 删除指定索引
del numbers[0]
print(f"del numbers[0]后: {numbers}")

# 删除切片
del numbers[1:3]
print(f"del numbers[1:3]后: {numbers}")

# 清空列表
numbers.clear()
print(f"clear()后: {numbers}")
    
✏️ 修改元素方法:

# 修改元素示例
lst = [1, 2, 3, 4, 5]
print(f"原始列表: {lst}")

# 修改单个元素
lst[2] = 30
print(f"修改索引2后: {lst}")

# 通过切片修改
lst[1:4] = [20, 30, 40]
print(f"切片修改[1:4]后: {lst}")

# 切片长度可不同
lst[1:3] = [200]
print(f"切片修改[1:3]后: {lst}")

# 条件修改
for i in range(len(lst)):
    if lst[i] % 2 == 0:
        lst[i] *= 10
print(f"偶数乘10后: {lst}")

# 列表推导式修改
lst = [x * 2 if x % 2 == 0 else x for x in lst]
print(f"推导式修改后: {lst}")
    

3.3 列表查询与排序

列表的查询和排序操作是数据处理中的核心功能:

🔍 查询操作:

# 查询操作示例
lst = [1, 2, 3, 2, 4, 2, 5]
print(f"原始列表: {lst}")

# 查找元素索引
print(f"元素2首次出现位置: {lst.index(2)}")      # 1
print(f"从索引2开始查找2: {lst.index(2, 2)}")   # 3
print(f"元素2出现次数: {lst.count(2)}")         # 3

# 检查元素存在性
print(f"元素3是否存在: {3 in lst}")             # True
print(f"元素6是否存在: {6 in lst}")             # False

# 查找所有匹配元素的索引
def find_all_indices(lst, target):
    """查找所有匹配元素的索引"""
    return [i for i, x in enumerate(lst) if x == target]

print(f"元素2的所有位置: {find_all_indices(lst, 2)}")  # [1, 3, 5]
    
📊 排序与反转:

# 排序与反转示例
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print(f"原始列表: {numbers}")

# 基本排序
numbers.sort()  # 原地排序
print(f"升序排序: {numbers}")  # [1, 1, 2, 3, 4, 5, 6, 9]

numbers.sort(reverse=True)  # 降序排序
print(f"降序排序: {numbers}")  # [9, 6, 5, 4, 3, 2, 1, 1]

# 自定义排序
words = ["cat", "dog", "elephant", "ant", "zebra"]
words.sort(key=len)  # 按长度排序
print(f"按长度排序: {words}")  # ['ant', 'cat', 'dog', 'zebra', 'elephant']

words.sort(key=str.lower)  # 忽略大小写排序
print(f"忽略大小写排序: {words}")  # ['ant', 'cat', 'dog', 'elephant', 'zebra']

# 复杂对象排序
students = [
    {"name": "Alice", "age": 20, "grade": 85},
    {"name": "Bob", "age": 19, "grade": 92},
    {"name": "Charlie", "age": 21, "grade": 78}
]

# 按成绩排序
by_grade = sorted(students, key=lambda x: x["grade"], reverse=True)
print("按成绩排序:")
for student in by_grade:
    print(f"  {student['name']}: {student['grade']}")

# 按年龄排序
by_age = sorted(students, key=lambda x: x["age"])
print("按年龄排序:")
for student in by_age:
    print(f"  {student['name']}: {student['age']}岁")

# 多条件排序
by_grade_age = sorted(students, key=lambda x: (x["grade"], x["age"]), reverse=True)
print("按成绩和年龄排序:")
for student in by_grade_age:
    print(f"  {student['name']}: 成绩{student['grade']}, 年龄{student['age']}")

# 反转操作
numbers.reverse()
print(f"反转后: {numbers}")  # [1, 1, 2, 3, 4, 5, 6, 9]

# 使用reversed()函数
rev_iter = reversed(numbers)
rev_list = list(rev_iter)
print(f"reversed()结果: {rev_list}")  # [9, 6, 5, 4, 3, 2, 1, 1]
    

3.4 列表切片与拷贝

列表切片是Python的强大特性,而拷贝操作需要注意深浅拷贝的区别:

✂️ 切片操作详解:

# 切片操作详解
lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(f"原始列表: {lst}")

# 基本切片
print(f"lst[2:6]: {lst[2:6]}")      # [2, 3, 4, 5]
print(f"lst[:5]: {lst[:5]}")         # [0, 1, 2, 3, 4]
print(f"lst[5:]: {lst[5:]}")         # [5, 6, 7, 8, 9]
print(f"lst[-3:]: {lst[-3:]}")       # [7, 8, 9] (最后3个元素)

# 步长切片
print(f"lst[::2]: {lst[::2]}")       # [0, 2, 4, 6, 8] (偶数索引)
print(f"lst[1::2]: {lst[1::2]}")     # [1, 3, 5, 7, 9] (奇数索引)
print(f"lst[::3]: {lst[::3]}")       # [0, 3, 6, 9] (步长为3)

# 负步长(反向)
print(f"lst[::-1]: {lst[::-1]}")     # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (反转)
print(f"lst[::-2]: {lst[::-2]}")     # [9, 7, 5, 3, 1] (反向步长为2)

# 负索引切片
print(f"lst[-5:-2]: {lst[-5:-2]}")   # [5, 6, 7]
print(f"lst[-2:-5:-1]: {lst[-2:-5:-1]}")  # [8, 7, 6] (反向切片)

# 切片赋值
lst_copy = lst.copy()
lst_copy[2:5] = [20, 30, 40]
print(f"切片赋值后: {lst_copy}")

# 切片删除
lst_copy[1:4] = []
print(f"切片删除后: {lst_copy}")
    
📋 拷贝操作详解:

# 拷贝操作详解
import copy

# 原始列表(包含嵌套结构)
original = [1, [2, 3], {"a": 4, "b": 5}]
print(f"原始列表: {original}")

# 1. 引用赋值(不是拷贝)
reference = original
print(f"引用赋值后: {reference}")
print(f"内存地址相同: {id(original) == id(reference)}")  # True

# 修改引用会影响原列表
reference[0] = 100
print(f"修改引用后原列表: {original}")  # [100, [2, 3], {"a": 4, "b": 5}]

# 2. 浅拷贝
shallow = original.copy()  # 等同于 original[:]
print(f"浅拷贝后: {shallow}")
print(f"内存地址不同: {id(original) != id(shallow)}")  # True

# 修改浅拷贝的第一层元素不会影响原列表
shallow[0] = 200
print(f"修改浅拷贝第一层后原列表: {original}")  # [100, [2, 3], {"a": 4, "b": 5}]

# 但修改嵌套对象会影响原列表(因为共享同一对象)
shallow[1][0] = 20
print(f"修改浅拷贝嵌套层后原列表: {original}")  # [100, [20, 3], {"a": 4, "b": 5}]

# 3. 深拷贝
deep = copy.deepcopy(original)
print(f"深拷贝后: {deep}")
print(f"内存地址不同: {id(original) != id(deep)}")  # True

# 修改深拷贝的任何层都不会影响原列表
deep[1][1] = 30
deep[2]["a"] = 40
print(f"修改深拷贝后原列表: {original}")  # [100, [20, 3], {"a": 4, "b": 5}]
print(f"深拷贝: {deep}")  # [100, [20, 30], {"a": 40, "b": 5}]

# 性能对比
import time

def test_copy_performance():
    large_list = [[i] for i in range(10000)]
    
    # 测试浅拷贝
    start = time.time()
    shallow_copy = large_list.copy()
    shallow_time = time.time() - start
    
    # 测试深拷贝
    start = time.time()
    deep_copy = copy.deepcopy(large_list)
    deep_time = time.time() - start
    
    print(f"浅拷贝时间: {shallow_time:.4f}秒")
    print(f"深拷贝时间: {deep_time:.4f}秒")
    print(f"深拷贝比浅拷贝慢 {deep_time/shallow_time:.1f}倍")

test_copy_performance()
    

3.5 列表推导式

列表推导式是Python的优雅特性,可以用简洁的语法快速生成列表:

🎯 推导式语法详解:

# 列表推导式详解

# 1. 基础推导式
print("=== 基础推导式 ===")
squares = [x**2 for x in range(1, 11)]
print(f"1-10的平方: {squares}")

cubes = [x**3 for x in range(1, 6)]
print(f"1-5的立方: {cubes}")

# 2. 条件筛选推导式
print("\n=== 条件筛选推导式 ===")
numbers = list(range(1, 21))
evens = [x for x in numbers if x % 2 == 0]
odds = [x for x in numbers if x % 2 == 1]
print(f"偶数: {evens}")
print(f"奇数: {odds}")

# 筛选质数
def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            return False
    return True

primes = [x for x in range(2, 50) if is_prime(x)]
print(f"质数: {primes}")

# 3. 字符串处理推导式
print("\n=== 字符串处理推导式 ===")
words = ["hello", "world", "python", "programming", "computer"]
long_words = [word.upper() for word in words if len(word) > 5]
print(f"长单词转大写: {long_words}")

# 字符统计
sentence = "hello world python programming"
char_count = {char: sentence.count(char) for char in set(sentence) if char != ' '}
print(f"字符统计: {char_count}")

# 4. 嵌套推导式
print("\n=== 嵌套推导式 ===")
# 二维列表转一维
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(f"展平矩阵: {flattened}")

# 生成乘法表
multiplication_table = [[i*j for j in range(1, 6)] for i in range(1, 6)]
print("乘法表:")
for row in multiplication_table:
    print(f"  {row}")

# 5. 条件表达式推导式
print("\n=== 条件表达式推导式 ===")
# 绝对值
numbers_with_signs = [-1, 2, -3, 4, -5, 6, -7, 8]
abs_values = [x if x > 0 else -x for x in numbers_with_signs]
print(f"绝对值: {abs_values}")

# 奇偶分类
classified = ["偶数" if x % 2 == 0 else "奇数" for x in range(1, 11)]
print(f"奇偶分类: {classified}")

# 6. 字典推导式(扩展)
print("\n=== 字典推导式 ===")
word_lengths = {word: len(word) for word in words}
print(f"单词长度字典: {word_lengths}")

# 7. 集合推导式(扩展)
print("\n=== 集合推导式 ===")
unique_lengths = {len(word) for word in words}
print(f"单词长度集合: {unique_lengths}")

# 8. 性能对比
print("\n=== 性能对比 ===")
import time

def traditional_way(n):
    result = []
    for i in range(n):
        if i % 2 == 0:
            result.append(i**2)
    return result

def comprehension_way(n):
    return [i**2 for i in range(n) if i % 2 == 0]

n = 1000000
start = time.time()
traditional_way(n)
traditional_time = time.time() - start

start = time.time()
comprehension_way(n)
comprehension_time = time.time() - start

print(f"传统方式时间: {traditional_time:.4f}秒")
print(f"推导式时间: {comprehension_time:.4f}秒")
print(f"推导式比传统方式快 {traditional_time/comprehension_time:.1f}倍")
    

3.6 列表与其他数据结构转换

Python中不同数据结构之间可以相互转换,掌握这些转换方法很有用:

🔄 数据结构转换方法:

# 数据结构转换详解

# 1. 列表与字符串转换
print("=== 列表与字符串转换 ===")

# 列表转字符串
chars = ['H', 'e', 'l', 'l', 'o']
word = ''.join(chars)
print(f"字符列表: {chars}")
print(f"转字符串: {word}")

# 带分隔符的转换
fruits = ['apple', 'banana', 'cherry']
fruits_str = ', '.join(fruits)
print(f"水果列表: {fruits}")
print(f"转字符串: {fruits_str}")

# 字符串转列表
sentence = "Hello World Python Programming"
char_list = list(sentence)
word_list = sentence.split()
print(f"句子: {sentence}")
print(f"转字符列表: {char_list}")
print(f"转单词列表: {word_list}")

# 按特定分隔符分割
csv_line = "张三,25,北京,工程师"
csv_list = csv_line.split(',')
print(f"CSV行: {csv_line}")
print(f"分割后: {csv_list}")

# 2. 列表与元组转换
print("\n=== 列表与元组转换 ===")
numbers_list = [1, 2, 3, 4, 5]
numbers_tuple = tuple(numbers_list)
print(f"列表: {numbers_list}")
print(f"转元组: {numbers_tuple}")

# 元组转列表
coordinates = (10, 20, 30)
coordinates_list = list(coordinates)
print(f"坐标元组: {coordinates}")
print(f"转列表: {coordinates_list}")

# 3. 列表与集合转换
print("\n=== 列表与集合转换 ===")
duplicate_numbers = [1, 2, 2, 3, 3, 4, 5, 5]
unique_numbers = list(set(duplicate_numbers))
print(f"有重复的列表: {duplicate_numbers}")
print(f"去重后: {unique_numbers}")

# 注意:集合无序,转换后顺序可能改变
original_order = [3, 1, 4, 1, 5, 9, 2, 6]
set_conversion = list(set(original_order))
print(f"原始顺序: {original_order}")
print(f"集合转换后: {set_conversion}")

# 4. 列表与字典转换
print("\n=== 列表与字典转换 ===")
student_info = {"name": "张三", "age": 20, "grade": "A"}
keys_list = list(student_info.keys())
values_list = list(student_info.values())
items_list = list(student_info.items())
print(f"学生信息: {student_info}")
print(f"键列表: {keys_list}")
print(f"值列表: {values_list}")
print(f"键值对列表: {items_list}")

# 列表转字典(需要特定格式)
pairs = [("a", 1), ("b", 2), ("c", 3)]
dict_from_pairs = dict(pairs)
print(f"键值对列表: {pairs}")
print(f"转字典: {dict_from_pairs}")

# 5. 高级转换技巧
print("\n=== 高级转换技巧 ===")

# 嵌套结构转换
nested_data = [
    ["name", "age", "city"],
    ["张三", 25, "北京"],
    ["李四", 30, "上海"],
    ["王五", 28, "广州"]
]

# 转换为字典列表
headers = nested_data[0]
data_dicts = []
for row in nested_data[1:]:
    data_dicts.append(dict(zip(headers, row)))

print("嵌套数据:")
for row in nested_data:
    print(f"  {row}")

print("转换为字典列表:")
for data_dict in data_dicts:
    print(f"  {data_dict}")

# 6. 实际应用示例
print("\n=== 实际应用示例 ===")

# CSV数据处理
csv_data = [
    "姓名,年龄,职业,城市",
    "张三,25,工程师,北京",
    "李四,30,设计师,上海",
    "王五,28,教师,广州"
]

def parse_csv(csv_lines):
    """解析CSV数据"""
    if not csv_lines:
        return []
    
    headers = csv_lines[0].split(',')
    data = []
    
    for line in csv_lines[1:]:
        values = line.split(',')
        row_dict = dict(zip(headers, values))
        data.append(row_dict)
    
    return data

parsed_data = parse_csv(csv_data)
print("解析后的CSV数据:")
for item in parsed_data:
    print(f"  {item}")

# 7. 性能考虑
print("\n=== 性能考虑 ===")
import time

def test_conversion_performance():
    large_list = list(range(100000))
    
    # 测试列表转元组
    start = time.time()
    tuple_result = tuple(large_list)
    tuple_time = time.time() - start
    
    # 测试列表转集合
    start = time.time()
    set_result = set(large_list)
    set_time = time.time() - start
    
    print(f"列表转元组时间: {tuple_time:.4f}秒")
    print(f"列表转集合时间: {set_time:.4f}秒")

test_conversion_performance()
    

4. 实际应用案例

4.1 学生成绩管理系统

这是一个典型的CS106A项目,展示如何使用列表管理学生数据:


# 学生成绩管理系统
class Student:
    def __init__(self, name, student_id):
        self.name = name
        self.student_id = student_id
        self.grades = []
    
    def add_grade(self, grade):
        if 0 <= grade <= 100:
            self.grades.append(grade)
        else:
            print(f"无效成绩: {grade}")
    
    def get_average(self):
        if not self.grades:
            return 0
        return sum(self.grades) / len(self.grades)
    
    def get_letter_grade(self):
        avg = self.get_average()
        if avg >= 90: return 'A'
        elif avg >= 80: return 'B'
        elif avg >= 70: return 'C'
        elif avg >= 60: return 'D'
        else: return 'F'

# 创建学生列表
students = [
    Student("Alice", "001"),
    Student("Bob", "002"),
    Student("Charlie", "003")
]

# 添加成绩
students[0].add_grade(95)
students[0].add_grade(88)
students[1].add_grade(92)
students[1].add_grade(85)
students[2].add_grade(78)
students[2].add_grade(82)

# 分析成绩
print("=== 学生成绩报告 ===")
for student in students:
    print(f"{student.name} (ID: {student.student_id}):")
    print(f"  成绩: {student.grades}")
    print(f"  平均分: {student.get_average():.1f}")
    print(f"  等级: {student.get_letter_grade()}")
    print()

# 班级统计
all_grades = [grade for student in students for grade in student.grades]
print(f"班级平均分: {sum(all_grades) / len(all_grades):.1f}")
print(f"最高分: {max(all_grades)}")
print(f"最低分: {min(all_grades)}")
    

4.2 图像像素处理

使用嵌套列表表示图像像素,这是计算机图形学的基础:


# 图像像素处理示例
def create_image(width, height, color=(255, 255, 255)):
    """创建指定尺寸的图像"""
    return [[color for _ in range(width)] for _ in range(height)]

def set_pixel(image, x, y, color):
    """设置指定位置的像素颜色"""
    if 0 <= y < len(image) and 0 <= x < len(image[0]):
        image[y][x] = color

def draw_rectangle(image, x1, y1, x2, y2, color):
    """绘制矩形"""
    for y in range(y1, y2 + 1):
        for x in range(x1, x2 + 1):
            set_pixel(image, x, y, color)

def draw_circle(image, center_x, center_y, radius, color):
    """绘制圆形(使用中点圆算法)"""
    x, y = radius, 0
    err = 0
    
    while x >= y:
        set_pixel(image, center_x + x, center_y + y, color)
        set_pixel(image, center_x + y, center_y + x, color)
        set_pixel(image, center_x - y, center_y + x, color)
        set_pixel(image, center_x - x, center_y + y, color)
        set_pixel(image, center_x - x, center_y - y, color)
        set_pixel(image, center_x - y, center_y - x, color)
        set_pixel(image, center_x + y, center_y - x, color)
        set_pixel(image, center_x + x, center_y - y, color)
        
        if err <= 0:
            y += 1
            err += 2*y + 1
        if err > 0:
            x -= 1
            err -= 2*x + 1

def save_image(image, filename):
    """保存图像到文件(简化版)"""
    with open(filename, 'w') as f:
        f.write(f"P3\n{len(image[0])} {len(image)}\n255\n")
        for row in image:
            for pixel in row:
                f.write(f"{pixel[0]} {pixel[1]} {pixel[2]} ")
            f.write("\n")

# 创建图像并绘制
img = create_image(100, 100, (255, 255, 255))  # 白色背景
draw_rectangle(img, 20, 20, 80, 80, (255, 0, 0))  # 红色矩形
draw_circle(img, 50, 50, 30, (0, 0, 255))  # 蓝色圆形

print("图像创建完成!")
print(f"图像尺寸: {len(img[0])} x {len(img)}")
print(f"中心像素颜色: {img[50][50]}")
    

4.3 游戏状态管理

使用列表管理游戏状态,这是游戏开发中的常见应用:


# 简单的井字棋游戏状态管理
class TicTacToe:
    def __init__(self):
        self.board = [[' ' for _ in range(3)] for _ in range(3)]
        self.current_player = 'X'
        self.game_over = False
    
    def make_move(self, row, col):
        """在指定位置下棋"""
        if self.game_over or row < 0 or row > 2 or col < 0 or col > 2:
            return False
        
        if self.board[row][col] != ' ':
            return False
        
        self.board[row][col] = self.current_player
        
        if self.check_winner(row, col):
            self.game_over = True
            return True
        
        if self.is_board_full():
            self.game_over = True
            return True
        
        self.current_player = 'O' if self.current_player == 'X' else 'X'
        return True
    
    def check_winner(self, row, col):
        """检查是否有获胜者"""
        player = self.board[row][col]
        
        # 检查行
        if all(self.board[row][c] == player for c in range(3)):
            return True
        
        # 检查列
        if all(self.board[r][col] == player for r in range(3)):
            return True
        
        # 检查对角线
        if row == col and all(self.board[i][i] == player for i in range(3)):
            return True
        
        if row + col == 2 and all(self.board[i][2-i] == player for i in range(3)):
            return True
        
        return False
    
    def is_board_full(self):
        """检查棋盘是否已满"""
        return all(self.board[r][c] != ' ' for r in range(3) for c in range(3))
    
    def display_board(self):
        """显示棋盘"""
        print("  0 1 2")
        for i, row in enumerate(self.board):
            print(f"{i} {'|'.join(row)}")
            if i < 2:
                print("  -----")
        print()

# 游戏演示
game = TicTacToe()
print("井字棋游戏开始!")
print("玩家X先手")

moves = [(0, 0), (1, 1), (0, 1), (2, 2), (0, 2)]  # 预设移动

for i, (row, col) in enumerate(moves):
    if game.make_move(row, col):
        print(f"玩家{game.current_player}在位置({row}, {col})下棋")
        game.display_board()
        
        if game.game_over:
            if game.is_board_full():
                print("游戏结束,平局!")
            else:
                winner = 'O' if game.current_player == 'X' else 'X'
                print(f"玩家{winner}获胜!")
            break
    else:
        print(f"无效移动: ({row}, {col})")
        break
    

5. 高级概念与最佳实践

5.1 列表性能考虑

理解列表操作的性能特征对于编写高效代码很重要:

⚡ 性能提示:

# 性能对比示例
import time

def measure_time(func, *args):
    """测量函数执行时间"""
    start_time = time.time()
    result = func(*args)
    end_time = time.time()
    return result, end_time - start_time

# 测试不同操作的性能
def test_append(n):
    lst = []
    for i in range(n):
        lst.append(i)
    return lst

def test_insert(n):
    lst = []
    for i in range(n):
        lst.insert(0, i)  # 在开头插入
    return lst

def test_extend(n):
    lst = []
    for i in range(0, n, 1000):
        lst.extend(range(i, min(i+1000, n)))
    return lst

# 性能测试
n = 10000
print(f"测试规模: {n} 个元素")
print()

_, append_time = measure_time(test_append, n)
print(f"append() 时间: {append_time:.4f} 秒")

_, insert_time = measure_time(test_insert, n)
print(f"insert(0) 时间: {insert_time:.4f} 秒")

_, extend_time = measure_time(test_extend, n)
print(f"extend() 时间: {extend_time:.4f} 秒")

print(f"\ninsert(0) 比 append() 慢 {insert_time/append_time:.1f} 倍")
    

5.2 列表与函数式编程

Python支持函数式编程范式,列表操作可以更加优雅:


# 函数式编程风格的列表操作
from functools import reduce
import operator

# 数据
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 使用map进行函数映射
squares = list(map(lambda x: x**2, numbers))
print(f"平方数: {squares}")

# 使用filter进行过滤
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(f"偶数: {evens}")

# 使用reduce进行累积操作
sum_all = reduce(operator.add, numbers)
product_all = reduce(operator.mul, numbers)
print(f"总和: {sum_all}")
print(f"乘积: {product_all}")

# 组合使用
result = reduce(operator.add, 
               map(lambda x: x**2, 
                   filter(lambda x: x % 2 == 0, numbers)))
print(f"偶数的平方和: {result}")

# 使用itertools模块
from itertools import chain, combinations

# 展平嵌套列表
nested = [[1, 2], [3, 4], [5, 6]]
flattened = list(chain.from_iterable(nested))
print(f"展平结果: {flattened}")

# 生成组合
combs = list(combinations(numbers[:5], 3))
print(f"5个数中取3个的组合数: {len(combs)}")
print(f"前5个组合: {combs[:5]}")
    

5.3 错误处理与调试

编写健壮的列表操作代码需要适当的错误处理:


# 错误处理示例
def safe_list_operations():
    """演示安全的列表操作"""
    
    # 1. 索引越界处理
    try:
        lst = [1, 2, 3]
        value = lst[10]
    except IndexError as e:
        print(f"索引错误: {e}")
        value = None
    
    # 2. 类型检查
    def process_numbers(numbers):
        if not isinstance(numbers, list):
            raise TypeError("参数必须是列表类型")
        
        if not all(isinstance(x, (int, float)) for x in numbers):
            raise ValueError("列表元素必须是数字")
        
        return sum(numbers) / len(numbers)
    
    # 测试类型检查
    try:
        result = process_numbers([1, 2, 3, "4"])
    except (TypeError, ValueError) as e:
        print(f"处理错误: {e}")
    
    # 3. 空列表处理
    def safe_pop(lst):
        """安全地弹出元素"""
        if not lst:
            return None
        return lst.pop()
    
    # 4. 列表验证
    def validate_list_structure(lst, expected_length=None, element_type=None):
        """验证列表结构"""
        if not isinstance(lst, list):
            return False, "不是列表类型"
        
        if expected_length is not None and len(lst) != expected_length:
            return False, f"长度不匹配,期望{expected_length},实际{len(lst)}"
        
        if element_type is not None:
            if not all(isinstance(x, element_type) for x in lst):
                return False, f"元素类型不匹配,期望{element_type}"
        
        return True, "验证通过"
    
    # 测试验证函数
    test_lists = [
        [1, 2, 3],
        [1, "2", 3],
        "not a list",
        [1, 2]
    ]
    
    for test_lst in test_lists:
        is_valid, message = validate_list_structure(test_lst, 3, int)
        print(f"列表 {test_lst}: {message}")

# 运行错误处理示例
safe_list_operations()
    

6. 编程练习与挑战

6.1 基础练习

🎯 练习1:列表基础操作

完成以下函数实现:

  1. 编写函数 find_duplicates(lst),找出列表中所有重复的元素
  2. 编写函数 rotate_list(lst, k),将列表向右旋转k个位置
  3. 编写函数 flatten_nested(lst),将任意深度的嵌套列表展平

# 练习1的参考答案
def find_duplicates(lst):
    """找出列表中所有重复的元素"""
    seen = set()
    duplicates = set()
    
    for item in lst:
        if item in seen:
            duplicates.add(item)
        else:
            seen.add(item)
    
    return list(duplicates)

def rotate_list(lst, k):
    """将列表向右旋转k个位置"""
    if not lst:
        return lst
    
    k = k % len(lst)  # 处理k大于列表长度的情况
    return lst[-k:] + lst[:-k]

def flatten_nested(lst):
    """将任意深度的嵌套列表展平"""
    result = []
    
    for item in lst:
        if isinstance(item, list):
            result.extend(flatten_nested(item))
        else:
            result.append(item)
    
    return result

# 测试函数
test_list = [1, 2, 2, 3, 4, 4, 5]
print(f"重复元素: {find_duplicates(test_list)}")

test_rotate = [1, 2, 3, 4, 5]
print(f"旋转2位: {rotate_list(test_rotate, 2)}")

test_nested = [1, [2, 3], [4, [5, 6]], 7]
print(f"展平结果: {flatten_nested(test_nested)}")
    

6.2 中级挑战

🚀 练习2:算法实现

实现以下算法:

  1. 实现快速排序算法 quicksort(lst)
  2. 实现二分查找算法 binary_search(lst, target)
  3. 实现滑动窗口算法 max_sum_subarray(lst, k)

# 练习2的参考答案
def quicksort(lst):
    """快速排序算法"""
    if len(lst) <= 1:
        return lst
    
    pivot = lst[len(lst) // 2]
    left = [x for x in lst if x < pivot]
    middle = [x for x in lst if x == pivot]
    right = [x for x in lst if x > pivot]
    
    return quicksort(left) + middle + quicksort(right)

def binary_search(lst, target):
    """二分查找算法(要求列表已排序)"""
    left, right = 0, len(lst) - 1
    
    while left <= right:
        mid = (left + right) // 2
        if lst[mid] == target:
            return mid
        elif lst[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    
    return -1

def max_sum_subarray(lst, k):
    """滑动窗口:找出长度为k的子数组的最大和"""
    if len(lst) < k:
        return None
    
    # 计算第一个窗口的和
    current_sum = sum(lst[:k])
    max_sum = current_sum
    
    # 滑动窗口
    for i in range(k, len(lst)):
        current_sum = current_sum - lst[i - k] + lst[i]
        max_sum = max(max_sum, current_sum)
    
    return max_sum

# 测试算法
test_numbers = [64, 34, 25, 12, 22, 11, 90]
print(f"原始列表: {test_numbers}")
print(f"快速排序: {quicksort(test_numbers)}")

sorted_numbers = quicksort(test_numbers)
print(f"二分查找25: 索引 {binary_search(sorted_numbers, 25)}")

test_array = [1, 4, 2, 10, 2, 3, 1, 0, 20]
print(f"数组: {test_array}")
print(f"长度为3的子数组最大和: {max_sum_subarray(test_array, 3)}")
    

6.3 高级项目

💻 练习3:综合项目

实现一个简单的图书管理系统,包含以下功能:

  1. 添加、删除、查找图书
  2. 按不同条件排序图书
  3. 统计图书信息
  4. 导出图书列表

# 练习3的参考答案
class Book:
    def __init__(self, title, author, year, genre, pages):
        self.title = title
        self.author = author
        self.year = year
        self.genre = genre
        self.pages = pages
    
    def __str__(self):
        return f"{self.title} by {self.author} ({self.year})"
    
    def to_dict(self):
        return {
            'title': self.title,
            'author': self.author,
            'year': self.year,
            'genre': self.genre,
            'pages': self.pages
        }

class Library:
    def __init__(self):
        self.books = []
    
    def add_book(self, book):
        """添加图书"""
        self.books.append(book)
        print(f"已添加: {book}")
    
    def remove_book(self, title):
        """根据标题删除图书"""
        for i, book in enumerate(self.books):
            if book.title.lower() == title.lower():
                removed = self.books.pop(i)
                print(f"已删除: {removed}")
                return True
        print(f"未找到图书: {title}")
        return False
    
    def find_book(self, title):
        """根据标题查找图书"""
        for book in self.books:
            if book.title.lower() == title.lower():
                return book
        return None
    
    def search_by_author(self, author):
        """根据作者查找图书"""
        return [book for book in self.books if author.lower() in book.author.lower()]
    
    def sort_books(self, key='title', reverse=False):
        """排序图书"""
        if key == 'title':
            self.books.sort(key=lambda x: x.title.lower(), reverse=reverse)
        elif key == 'author':
            self.books.sort(key=lambda x: x.author.lower(), reverse=reverse)
        elif key == 'year':
            self.books.sort(key=lambda x: x.year, reverse=reverse)
        elif key == 'pages':
            self.books.sort(key=lambda x: x.pages, reverse=reverse)
    
    def get_statistics(self):
        """获取统计信息"""
        if not self.books:
            return "图书馆暂无图书"
        
        total_books = len(self.books)
        total_pages = sum(book.pages for book in self.books)
        avg_pages = total_pages / total_books
        genres = {}
        years = {}
        
        for book in self.books:
            genres[book.genre] = genres.get(book.genre, 0) + 1
            years[book.year] = years.get(book.year, 0) + 1
        
        return {
            'total_books': total_books,
            'total_pages': total_pages,
            'avg_pages': avg_pages,
            'genres': genres,
            'years': years
        }
    
    def export_books(self, filename):
        """导出图书列表到文件"""
        with open(filename, 'w', encoding='utf-8') as f:
            f.write("图书列表\n")
            f.write("=" * 50 + "\n")
            for i, book in enumerate(self.books, 1):
                f.write(f"{i}. {book}\n")
                f.write(f"   类型: {book.genre}, 页数: {book.pages}\n\n")
        print(f"图书列表已导出到 {filename}")
    
    def display_books(self):
        """显示所有图书"""
        if not self.books:
            print("图书馆暂无图书")
            return
        
        print("\n=== 图书列表 ===")
        for i, book in enumerate(self.books, 1):
            print(f"{i}. {book}")
            print(f"   类型: {book.genre}, 页数: {book.pages}")

# 使用示例
library = Library()

# 添加图书
books_data = [
    ("Python编程", "张三", 2020, "编程", 300),
    ("数据结构", "李四", 2019, "计算机科学", 250),
    ("算法导论", "王五", 2018, "计算机科学", 500),
    ("机器学习", "赵六", 2021, "人工智能", 400)
]

for title, author, year, genre, pages in books_data:
    book = Book(title, author, year, genre, pages)
    library.add_book(book)

print("\n" + "="*50)
library.display_books()

print("\n" + "="*50)
print("按年份排序:")
library.sort_books('year', reverse=True)
library.display_books()

print("\n" + "="*50)
stats = library.get_statistics()
print("统计信息:")
for key, value in stats.items():
    print(f"{key}: {value}")

# 查找图书
found = library.find_book("Python编程")
if found:
    print(f"\n找到图书: {found}")

# 导出图书列表
library.export_books("books.txt")
    

7. 总结与下一步学习

📚 本课程要点总结

🔗 下一步学习建议:

8. 作业与评估

📝 作业11:Python列表综合应用

完成以下编程任务,展示你对Python列表的掌握程度:

基础任务(60分):

  1. 定义一个列表,存储5个同学的姓名,并输出每个姓名。(10分)
  2. 输入一组整数,输出其中的最大值和平均值。(10分)
  3. 用列表推导式生成1~100内所有偶数的平方列表。(10分)
  4. 实现一个函数,将两个列表合并并去重。(15分)
  5. 编写程序,找出列表中所有重复的元素。(15分)

进阶任务(40分):

  1. 使用列表推导式生成一个3x3的矩阵,对角线元素为1,其他为0。(20分)
  2. 实现一个简单的学生成绩管理系统,包含添加、删除、查询、统计功能。(20分)

提交要求:

💡 学习提示:

列表是Python编程的基础,掌握好列表操作将为后续学习打下坚实基础。建议: