《Python AI 应用开发入门》第 2.5 节。
使用列表保存可变序列,使用元组表示不应随意修改的有序数据。
本节目标
学完本节后,你应当能够:
1. 为什么需要容器
单独保存三条消息需要三个变量:
message_1 = "你好"message_2 = "请解释列表"message_3 = "谢谢"
当消息数量变化时,这种写法很难管理。列表可以按顺序保存任意数量的值:
messages = ["你好", "请解释列表", "谢谢"]
列表有顺序、允许重复,并且可以修改。
2. 创建列表
使用方括号:
messages = ["你好", "请解释列表", "谢谢"]empty_history = []
列表可以保存不同类型:
mixed_values = ["demo-model", 3, True, None]
语法允许混合,但业务数据最好保持一致、含义清楚。例如 messages 中都保存消息文本,后续更容易处理。
print(type(messages))print(len(messages))
len() 返回元素数量。
3. 索引和切片
列表同样从索引 0 开始:
messages = ["你好", "请解释列表", "谢谢"]print(messages[0])print(messages[1])print(messages[-1])
修改指定位置:
messages[1] = "请用例子解释列表"
切片返回一个新列表:
print(messages[:2])print(messages[-2:])print(messages[::2])
索引越界会触发 IndexError:
# print(messages[10])
访问前可以先判断长度:
if messages: print(messages[-1])else: print("暂无消息")
4. 添加元素
append() 追加一个元素
messages = []messages.append("你好")messages.append("请解释变量")
insert() 插入指定位置
messages.insert(0, "系统提示:请简洁回答")
extend() 添加多个元素
more_messages = ["举个例子", "谢谢"]messages.extend(more_messages)
注意区别:
messages.append(["A", "B"]) # 把整个列表作为一个元素messages.extend(["C", "D"]) # 分别加入 C 和 D
5. 删除元素
按值删除
messages = ["你好", "重复消息", "谢谢"]if "重复消息" in messages: messages.remove("重复消息")
remove() 只删除第一个匹配值;找不到时会触发 ValueError。
按位置取出并删除
last_message = messages.pop()print(last_message)
pop() 默认处理最后一个元素,也可以传入索引:
first_message = messages.pop(0)
空列表调用 pop() 会触发 IndexError。
清空列表
messages.clear()
6. 查找、计数和排序
models = ["demo-pro", "demo-mini", "demo-pro"]print("demo-mini" in models)print(models.index("demo-mini"))print(models.count("demo-pro"))
index() 找不到时会触发 ValueError,所以不确定时先使用 in。
排序:
models.sort()print(models)
sort() 会修改原列表,并返回 None:
result = models.sort()print(result) # None
如果要保留原列表,可以使用:
original = ["demo-pro", "demo-mini"]sorted_models = sorted(original)
反转:
models.reverse()
7. 列表是可变的
messages = ["你好"]history = messageshistory.append("请解释列表")print(messages)
输出:
['你好', '请解释列表']
history = messages 没有复制列表,只是让两个变量指向同一个列表。
需要浅复制这一层列表时:
messages = ["你好"]history_copy = messages.copy()history_copy.append("新消息")print(messages)print(history_copy)
切片 messages[:] 也能创建浅复制。嵌套列表的深层复制会在后续课程按需要学习。
8. 列表中的列表
二维结构可以保存分组数据:
conversations = [ ["你好", "你好,有什么可以帮你?"], ["什么是列表?", "列表是有顺序的可变容器。"],]print(conversations[0])print(conversations[0][1])
但只靠位置表达“用户”和“助手”容易混淆。下一节会使用字典给字段命名。
9. 元组
元组与列表一样有顺序、允许重复,但创建后不能修改元素:
supported_roles = ("system", "user", "assistant")screen_size = (1280, 720)
读取和切片与列表类似:
print(supported_roles[0])print(supported_roles[-1])print(supported_roles[:2])
不能赋值:
# supported_roles[0] = "admin"
这会触发 TypeError。
只有一个元素的元组必须保留逗号:
one_role = ("user",)not_a_tuple = ("user")print(type(one_role))print(type(not_a_tuple))
10. 元组解包
model_config = ("demo-mini", 0.7, 500)model_name, temperature, max_tokens = model_configprint(model_name)print(temperature)print(max_tokens)
左侧变量数量必须与元组元素数量一致,否则会触发 ValueError。
交换两个变量也可以使用解包:
primary_model = "demo-pro"backup_model = "demo-mini"primary_model, backup_model = backup_model, primary_model
11. 列表还是元组
元组的“不可变”表达了意图,但它不是安全边界。程序中的权限和数据保护不能只依赖元组。
12. 章节项目的第一版历史记录
messages = []first_message = input("第一条消息:").strip()second_message = input("第二条消息:").strip()if first_message: messages.append(first_message)if second_message: messages.append(second_message)print(f"消息总数:{len(messages)}")if messages: print(f"最新消息:{messages[-1]}") print(f"最近两条:{messages[-2:]}")else: print("暂无消息")
目前只能固定接收两次输入。第 2.7 节会使用循环支持任意数量。
动手练习
练习 1:聊天历史操作
创建 message_collections.py:
练习 2:观察共享列表
运行并解释:
messages = ["A"]backup = messagesbackup.append("B")print(messages)print(backup)
然后把第二行改成 backup = messages.copy(),比较结果。
练习 3:固定模型配置
使用元组保存模型名、温度和最大输出长度。通过解包把三项赋给变量,并使用 f-string 输出配置。
随堂小测
- 2.
append() 与 extend() 有什么区别? - 3.
remove() 与 pop() 分别按什么删除? - 4. 为什么
result = items.sort() 后 result 是 None? - 5.
backup = messages 会复制列表吗? - 6. 单元素元组为什么要写成
("user",)?
参考答案
- 2.
append() 把一个值作为一个元素追加;extend() 把可迭代数据中的多个元素逐个加入。 - 3.
remove() 按值删除第一个匹配项;pop() 按索引取出并删除。 - 4.
sort() 原地修改列表,不返回排序后的新列表。 - 6. 逗号才让 Python 把它识别为元组;只有括号仍是字符串。
- 7. 列表,因为聊天历史需要持续新增、删除和清空。
本节完成检查