引言
想象一下,你要管理一个繁忙的快递站。
- 列表(List) 就像那一排排整齐的货架,每个格子上放着一个包裹(元素),你有它们的顺序编号(索引)。你可以快速找到第 5 个货架上的东西,也可以轻松地在末尾新增一个包裹。
本文深入讲解 Python 中的列表(List)和字典(Dictionary)两种核心数据结构,涵盖创建、访问、增删改查及切片操作。同时详细剖析 for 循环与 while 循环的语法、应用场景及进阶技巧(如 enumerate、zip、嵌套循环),并通过代码示例对比两者的区别与选择指南,帮助读者掌握数据流转与自动化处理的核心法则。

想象一下,你要管理一个繁忙的快递站。
那么循环呢?
for循环 就像你沿着货架从头到尾依次检查每一个包裹('遍历'),这是你知道要处理所有物品时的首选。while循环 则像是一个'直到…才停止'的指令。比如,'直到货架清空,才停止搬运'。你并不一开始就知道要循环多少次,而是由一个条件来决定的。在 Python 的世界里,几乎每一个有趣的项目,都离不开这四者的精妙配合。本文将带你深入这个'快递站',掌握让数据流转自如的核心法则。
想象一下你去超市购物的情景。你推着一辆购物车,里面按顺序放着:牛奶、面包、鸡蛋、苹果。
在 Python 中,这个购物车就是一个列表(List):
shopping_list = ['牛奶', '面包', '鸡蛋', '苹果']
列表的本质:一个有序、可变的元素集合,像是给你的数据物品准备的一排编号货架。
fruits = ['苹果', '香蕉', '橙子']
numbers = [1, 2, 3, 4, 5]
mixed = [1, 'hello', 3.14, True] # 列表可以包含不同类型的元素
chars = list('Python') # ['P', 'y', 't', 'h', 'o', 'n']
range_list = list(range(5)) # [0, 1, 2, 3, 4]
empty_list = []
列表使用索引(index) 来定位元素,索引从 0 开始!
colors = ['红', '橙', '黄', '绿', '青', '蓝', '紫']
# 正向索引(从前往后)
print(colors[0]) # '红' - 第一个元素
print(colors[3]) # '绿' - 第四个元素
# 负向索引(从后往前)
print(colors[-1]) # '紫' - 最后一个元素
print(colors[-2]) # '蓝' - 倒数第二个
# 注意:索引越界会报错!
# print(colors[7]) # ❌ IndexError: list index out of range
小技巧:使用 len() 函数获取列表长度。
length = len(colors) # 7
last_index = length - 1 # 6
增加元素:
todo_list = ['学习 Python', '玩游戏']
# 在末尾添加
todo_list.append('运动') # ['学习 Python', '玩游戏', '运动']
# 在指定位置插入
todo_list.insert(1, '吃午饭') # ['学习 Python', '吃午饭', '玩游戏', '运动']
# 合并另一个列表
todo_list.extend(['阅读', '休息']) # 现在有 6 个任务了
删除元素:
# 按值删除(删除第一个匹配项)
todo_list.remove('吃午饭')
# 按索引删除
del todo_list[0]
# 删除并返回最后一个
popped_item = todo_list.pop()
# 删除并返回索引 1 的元素
popped_item = todo_list.pop(1)
# 清空列表
todo_list.clear() # 列表变空:[]
修改元素:
colors = ['红', '橙', '黄']
colors[1] = '粉红' # 直接赋值修改
# 现在 colors 是:['红', '粉红', '黄']
查找元素:
colors = ['红', '橙', '黄', '绿', '蓝']
# 检查元素是否存在
if '绿' in colors:
print("绿色在列表中!")
# 获取元素索引
index = colors.index('黄') # 2
# colors.index('紫') # ❌ 如果不存在会报错
# 统计出现次数
count = colors.count('红') # 1
切片(Slicing) - 获取子列表:
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 基本格式:list[start:end:step]
print(numbers[2:6]) # [2, 3, 4, 5] # 包含 2,不包含 6
print(numbers[:5]) # [0, 1, 2, 3, 4] # 从头开始
print(numbers[5:]) # [5, 6, 7, 8, 9] # 到末尾结束
print(numbers[::2]) # [0, 2, 4, 6, 8] # 每隔一个取一个
print(numbers[::-1]) # 反转列表![9, 8, 7, ... , 0]
# 切片创建的是新列表,不影响原列表
first_five = numbers[:5] # 前五个元素的副本
遍历列表:
# 方法 1:直接遍历元素
fruits = ['苹果', '香蕉', '橙子']
for fruit in fruits:
print(f"我喜欢吃{fruit}")
# 方法 2:同时获取索引和元素
for index, fruit in enumerate(fruits):
print(f"第{index}个水果是:{fruit}")
# 输出:第 0 个水果是:苹果...
来尝试一下吧,试着完成下面的小挑战:
# 单词频率统计(为学习字典做准备)
text = "apple banana apple orange banana apple"
words = text.split() # 统计每个单词出现的次数
咱们刚刚学了列表,想象这样一个场景:你需要管理一个班级的学生信息。用列表可以这样写:
students = ['张三', 18, '男', '李四', 19, '女', '王五', 20, '男']
问题来了:你怎么快速找到'李四'的年龄?你得记住年龄在列表中的位置,然后通过 students[4] 来获取。如果数据再多一些,这种'位置记忆'就变得极其困难。
字典就是为了解决这个问题而生的:
student = {'姓名': '张三', '年龄': 18, '性别': '男'}
字典的本质:一种键值对(key-value) 的映射结构,让你能通过一个有意义的关键词(键) 快速找到对应的数据(值)。
现实世界的字典
就像查英语字典:
快递取件系统
在 Python 中,字典就是这样一个高效的查询系统。
方法 1:花括号直接创建(最常用)
student = {'姓名': '张三', '年龄': 18, '专业': '计算机'}
book = {'标题': 'Python 编程', '价格': 89.9, '库存': True}
方法 2:dict() 函数创建
empty_dict = dict() # 空字典
person = dict(name='李四', age=25) # 关键字参数方式
方法 3:从列表的元组对创建
pairs = [('姓名', '王五'), ('年龄', 20)]
person = dict(pairs) # {'姓名': '王五', '年龄': 20}
方法 4:字典推导式(后面会详讲)
squares = {x: x**2 for x in range(5)} # {0:0, 1:1, 2:4, 3:9, 4:16}
特殊:键的类型(必须是不可变类型)
valid_keys = {
'字符串': 'value1', # ✅ 字符串
123: 'value2', # ✅ 整数
(1, 2, 3): 'value3', # ✅ 元组(不可变)
# ['列表']: 'value4' # ❌ 列表不能作为键(可变)
}
基本访问方式:
student = {'姓名': '张三', '年龄': 18, '专业': '计算机'}
# 通过键访问值(最常用)
print(student['姓名']) # '张三'
print(student['年龄']) # 18
# ❌ 访问不存在的键会报错!
# print(student['地址']) # KeyError: '地址'
最保险的访问方法:
方法 1:get() 方法
address = student.get('地址') # 不存在返回 None
address = student.get('地址', '未填写') # 不存在返回默认值'未填写'
方法 2:in 关键字检查键是否存在
'地址' in student # 存在返回 True,不存在返回 False
方法 3:setdefault() - 获取值,如果不存在则设置默认值(非常实用!一行代码完成'如果不存在则初始化')
student.setdefault('成绩', []) # 如果'成绩'不存在,则设为空列表 []
student['成绩'].append(95) # 现在可以安全地添加成绩
增加/修改元素
config = {'主题': '暗色', '语言': '中文'}
# 添加新键值对
config['字体大小'] = 14 # 现在 config: {'主题': '暗色', '语言': '中文', '字体大小': 14}
# 修改现有键的值
config['主题'] = '亮色' # 现在 config: {'主题': '亮色', '语言': '中文', '字体大小': 14}
# 批量更新(合并字典)
config.update({'语言': '英文', '声音': True}) # 现在 config 包含了所有更新
删除元素
方法 1:del语句
del config['字体大小']
方法 2:pop() - 删除并返回值
language = config.pop('语言') # '英文'
方法 3:popitem() - 删除最后插入的键值对(Python 3.7+有序)
last_item = config.popitem() # 可能是 ('声音', True)
方法 4:clear() - 清空字典
config.clear() # {}
获取字典信息
employee = {'姓名': '王五', '部门': '技术部', '工号': 1001}
# 获取所有键
keys = employee.keys() # dict_keys(['姓名', '部门', '工号'])
# 获取所有值
values = employee.values() # dict_values(['王五', '技术部', 1001])
# 获取所有键值对
items = employee.items() # dict_items([('姓名', '王五'), ...])
# 注意:这些返回的是视图对象,会随字典变化
# 如果需要列表,可以转换:
key_list = list(employee.keys())
字典推导式
# 创建一个数字到平方的映射
squares = {x: x**2 for x in range(1, 6)} # {1:1, 2:4, 3:9, 4:16, 5:25}
# 过滤字典
scores = {'张三': 85, '李四': 92, '王五': 78, '赵六': 95}
high_scores = {name: score for name, score in scores.items() if score >= 90}
# {'李四': 92, '赵六': 95}
# 键值互换(注意值必须唯一)
inverted = {score: name for name, score in scores.items()}
字典合并(Python 3.9+)
# Python 3.9+ 的新语法
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
merged = dict1 | dict2 # {'a': 1, 'b': 3, 'c': 4}
# 注意:相同键时,后面的值覆盖前面的
默认字典(defaultdict)
from collections import defaultdict
# 传统方式:统计单词频率
words = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']
word_count = {}
for word in words:
if word in word_count:
word_count[word] += 1
else:
word_count[word] = 1
# 使用 defaultdict:自动初始化
word_count = defaultdict(int) # int() 默认返回 0
for word in words:
word_count[word] += 1 # 不需要检查 key 是否存在!
# defaultdict(<class 'int'>, {'apple': 3, 'banana': 2, 'orange': 1})
| 特性 | 列表(List) | 字典(Dictionary) |
|---|---|---|
| 核心概念 | 有序集合 | 键值对映射 |
| 访问方式 | 数字索引(0,1,2…) | 任意不可变键 |
| 顺序 | 保持插入顺序(重要!) | Python 3.7+ 保持插入顺序 |
| 查找速度 | O(n)(线性搜索) | O(1)(平均,哈希表) |
| 内存占用 | 较小 | 较大(需要存储键和值) |
| 典型用途 | 有序数据序列 | 关联数据、快速查找 |
选择指南:
数据分析挑战
# 给定销售数据,计算:
sales = [
{'product': 'A', 'amount': 100, 'month': 'Jan'},
{'product': 'B', 'amount': 150, 'month': 'Jan'},
{'product': 'A', 'amount': 200, 'month': 'Feb'},
{'product': 'C', 'amount': 50, 'month': 'Feb'},
]
# 1. 每种产品的总销售额
# 2. 每个月的总销售额
# 3. 最畅销的产品
想象一下,你需要给公司 100 名员工发送生日祝福邮件。手动操作需要:
这种重复模式在编程中太常见了!幸运的是,Python 为我们提供了 for 循环——让计算机自动处理重复任务的完美工具。
# 手动方式(不可行)
# print("你好,员工 1!")
# print("你好,员工 2!")
# ... 要写 98 行 print
# for 循环方式(自动化)
for 员工编号 in range(1, 101):
print(f"你好,员工{员工编号}!")
for 循环的本质:一种确定性循环,用于遍历序列中的每个元素并执行相同的操作。
最简形式
for 变量 in 可迭代对象:
# 缩进的代码块会被重复执行
执行操作 (变量)
一个具体例子
# 遍历水果列表
fruits = ['苹果', '香蕉', '橙子', '葡萄']
for fruit in fruits:
# 每次循环,fruit 依次取列表中的值
print(f"我喜欢吃{fruit}")
print("---") # 注意缩进!这两行都属于循环体
print("所有水果都展示完了!") # 这行在循环结束后执行
for 循环可以遍历任何'可迭代对象',主要包括:
1. 遍历列表(最常用)
# 计算总分
scores = [85, 92, 78, 90, 88]
total = 0
for score in scores:
total += score # 累加每个分数
print(f"总分:{total}") # 433
print(f"平均分:{total / len(scores)}") # 86.6
2. 遍历字符串
# 统计字符串中的元音字母
text = "Hello, Python!"
vowel_count = 0
for char in text:
# 遍历每个字符
if char.lower() in 'aeiou':
vowel_count += 1
print(f"元音字母个数:{vowel_count}") # 4 (e, o, o)
3. 遍历字典
# 遍历字典有不同的方式
student = {'姓名': '张三', '年龄': 18, '专业': '计算机'}
# 方式 1:遍历键
for key in student:
print(f"键:{key}")
# 方式 2:遍历值
for value in student.values():
print(f"值:{value}")
# 方式 3:同时遍历键和值(最常用!)
for key, value in student.items():
print(f"{key}:{value}")
4. 遍历 range() 对象
# range(stop): 0 到 stop-1
for i in range(5): # 0,1,2,3,4
print(i)
# range(start, stop): start 到 stop-1
for i in range(2, 6): # 2,3,4,5
print(i)
# range(start, stop, step): 带步长
for i in range(0, 10, 2): # 0,2,4,6,8
print(i)
# 倒序
for i in range(5, 0, -1): # 5,4,3,2,1
print(i)
5. 遍历其他可迭代对象
# 遍历元组
colors = ('红', '绿', '蓝')
for color in colors:
print(color)
# 遍历集合
unique_numbers = {1, 2, 3, 3, 2} # {1, 2, 3}
for num in unique_numbers:
print(num)
# 遍历文件行
with open('data.txt', 'r', encoding='utf-8') as file:
for line in file: # 逐行读取
print(line.strip()) # 去除换行符
1. enumerate():同时获取索引和值
fruits = ['苹果', '香蕉', '橙子']
# 传统方式(不推荐)
index = 0
for fruit in fruits:
print(f"第{index}个水果:{fruit}")
index += 1
# 使用 enumerate()(推荐!)
for index, fruit in enumerate(fruits):
print(f"第{index}个水果:{fruit}")
# 从 1 开始计数
for index, fruit in enumerate(fruits, start=1):
print(f"第{index}个水果:{fruit}")
2. zip():并行遍历多个序列
names = ['张三', '李四', '王五']
scores = [85, 92, 78]
subjects = ['数学', '语文', '英语']
# 同时遍历多个列表
for name, score in zip(names, scores):
print(f"{name}的成绩是{score}分")
# 遍历三个列表
for name, score, subject in zip(names, scores, subjects):
print(f"{name}的{subject}成绩是{score}分")
# 注意:zip 在最短序列结束时停止
list1 = [1, 2, 3]
list2 = ['a', 'b']
for num, char in zip(list1, list2): # 只循环 2 次
print(num, char)
3. 嵌套循环:循环中的循环
# 乘法表
print("乘法表:")
for i in range(1, 4): # 外层循环
for j in range(1, 4): # 内层循环
print(f"{i} × {j} = {i * j}", end="\t")
print() # 换行
# 输出:
# 乘法表:
# 1 × 1 = 1 1 × 2 = 2 1 × 3 = 3
# 2 × 1 = 2 2 × 2 = 4 2 × 3 = 6
# 3 × 1 = 3 3 × 2 = 6 3 × 3 = 9
4. 循环控制:break、continue、else
# break:提前结束整个循环
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for num in numbers:
if num > 5:
break # 当 num>5 时,立即结束循环
print(num) # 只输出 1,2,3,4,5
# continue:跳过当前迭代,继续下一次
for num in range(1, 11):
if num % 2 == 0: # 如果是偶数
continue # 跳过本次循环的剩余代码
print(num) # 只输出奇数:1,3,5,7,9
# else:循环正常结束后执行(没被 break 中断时)
for num in range(3):
print(num)
else:
print("循环正常结束!") # 会执行
for num in range(3):
if num == 1:
break
print(num)
else:
print("循环正常结束!") # 不会执行,因为被 break 中断了
5. 列表推导式:for 循环的简洁写法
# 传统方式:创建平方数列表
squares = []
for i in range(1, 6):
squares.append(i ** 2)
# 列表推导式:一行搞定
squares = [i ** 2 for i in range(1, 6)]
# 带条件的列表推导式
even_squares = [i ** 2 for i in range(1, 11) if i % 2 == 0]
# 字典推导式
squares_dict = {i: i ** 2 for i in range(1, 6)}
# 集合推导式
unique_lengths = {len(word) for word in ['apple', 'banana', 'apple', 'orange']}
文本分析器
# 分析一段文本的统计信息
text = """ Python 是一种高级编程语言,由 Guido van Rossum 于 1991 年创建。
它以简洁、易读的语法而闻名,广泛应用于 Web 开发、数据科学、人工智能等领域。 """
# 请计算:
# 1. 总字符数(不含空格和换行)
# 2. 总单词数
# 3. 每个单词出现的频率
# 4. 最长的单词
密码生成器
# 生成指定数量的随机密码
import random
import string
def generate_passwords(count, length=8):
passwords = []
# 你的代码写在这里
# 提示:使用嵌套循环
# 外层循环生成 count 个密码
# 内层循环生成每个密码的字符
return passwords # 测试
print(generate_passwords(3, 10))
想象这样一个场景:你在开发一个猜数字游戏,程序随机生成一个 1-100 的数字,玩家不断猜测,直到猜中为止。你无法提前知道玩家需要猜多少次——可能 1 次就中,也可能要猜 50 次。
import random
target_number = random.randint(1, 100)
guess_count = 0
# 我们不知道循环多少次,只知道继续的条件:没猜中
while True: # 看起来像是无限循环,但实际上有 break 退出
guess = int(input("请猜一个 1-100 的数字:"))
guess_count += 1
if guess < target_number:
print("猜小了!")
elif guess > target_number:
print("猜大了!")
else:
print(f"恭喜!你猜了{guess_count}次就猜中了!")
break # 猜中后退出循环
while 循环的本质:一种条件控制循环,只要条件为真就不断重复执行。它适用于循环次数不确定,但知道继续条件的场景。
最简形式
while 条件表达式:
# 条件为 True 时执行的代码块
执行操作 ()
# 通常需要在循环体内改变条件,否则可能无限循环!
一个具体例子
# 计数器示例
count = 0
while count < 5: # 条件:count 小于 5
print(f"当前计数:{count}")
count += 1 # 改变条件变量,这是避免无限循环的关键!
# 当 count 变成 5 时,条件 count<5 变为 False,循环结束
print("循环结束!")
条件的三种常见形式
1. 计数器控制(知道最大循环次数)
# 模拟加载进度条
progress = 0
total = 100
while progress < total:
progress += 10
print(f"加载中... {progress}%")
# 实际中这里可能会有 time.sleep(0.5) 模拟延迟
print("加载完成!")
2. 标志位控制(事件驱动)
# 用户输入验证系统
is_valid = False # 标志位
while not is_valid: # 当 is_valid 为 False 时继续循环
age_input = input("请输入年龄 (0-120): ")
if age_input.isdigit(): # 检查是否为数字
age = int(age_input)
if 0 <= age <= 120:
is_valid = True # 改变标志位,退出循环
print(f"年龄验证通过:{age}")
else:
print("年龄必须在 0-120 之间!")
else:
print("请输入有效的数字!")
print("继续处理其他逻辑...")
3. 哨兵值控制(特殊值结束)
# 收集学生成绩,直到输入 -1 结束
scores = []
print("请输入学生成绩 (输入 -1 结束):")
while True: # 看起来是无限循环
score_input = input("成绩:")
if score_input == "-1": # 哨兵值
break # 遇到哨兵值立即退出
if score_input.isdigit():
score = int(score_input)
scores.append(score)
else:
print("请输入数字!")
print(f"共收集{len(scores)}个成绩,平均分:{sum(scores)/len(scores):.2f}")
1. while-else 结构
# else 在循环正常结束时执行(非 break 退出)
count = 0
while count < 3:
print(f"尝试第{count+1}次")
# 这里可以是一些可能失败的操作
count += 1
else:
print("所有尝试都完成了!")
# 与 break 结合:else 不会执行
count = 0
while count < 5:
if count == 3:
print("提前结束!")
break
print(count)
count += 1
else:
print("这不会执行") # 因为循环被 break 中断了
2. 多个条件的组合
# 复合条件控制
attempts = 0
max_attempts = 3
success = False
while not success and attempts < max_attempts:
attempts += 1
print(f"第{attempts}次尝试...")
# 模拟操作,随机成功
import random
success = random.random() > 0.7 # 30% 成功概率
if success:
print("操作成功!")
elif attempts == max_attempts:
print("已达最大尝试次数,操作失败!")
3. 在 while 循环中模拟 for 循环
# 用 while 循环实现 for 循环的功能
fruits = ['苹果', '香蕉', '橙子']
# for 循环方式
for fruit in fruits:
print(fruit)
# while 循环方式
index = 0
while index < len(fruits):
print(fruits[index])
index += 1
4. 嵌套 while 循环
# 打印九九乘法表
print("九九乘法表:")
row = 1
while row <= 9:
col = 1
while col <= row: # 每行列数不超过行数
print(f"{col}×{row}={col*row:2d}", end=" ") # :2d 表示占 2 位右对齐
col += 1
print() # 换行
row += 1
什么是无限循环?
# ❌ 危险的无限循环
count = 0
while count < 5:
print(count) # 忘记增加 count,条件永远为 True!
# 程序会一直打印 0,直到手动停止
# ⚠️ 可能导致无限循环的情况
# 1. 忘记更新条件变量
# 2. 条件永远为 True (while True 且没有 break)
# 3. 逻辑错误导致条件无法变为 False
如何安全地使用无限循环
# ✅ 安全模式 1:明确退出条件
while True:
user_input = input("输入'quit'退出:")
if user_input.lower() == 'quit':
break # 明确的退出点
print(f"你输入了:{user_input}")
# ✅ 安全模式 2:添加安全计数器
max_iterations = 1000 # 安全阀
iteration = 0
while iteration < max_iterations: # 正常的业务逻辑
iteration += 1
if some_condition:
break
if iteration == max_iterations:
print("警告:达到最大循环次数!")
| 特性 | for 循环 | while 循环 |
|---|---|---|
| 循环条件 | 遍历可迭代对象 | 满足条件时继续 |
| 循环次数 | 确定(由序列长度决定) | 不确定 |
| 适用场景 | 遍历已知集合 | 条件满足时重复 |
| 控制方式 | 自动迭代 | 需手动更新条件 |
| 死循环风险 | 较低 | 较高(需谨慎) |
选择指南:
# for 循环:遍历已知集合
for student in students:
process_student(student)
# while 循环:条件控制
user_input = ""
while user_input.lower() != "quit":
user_input = input("请输入命令:")
process_command(user_input)

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online