zip()
是 Python 中非常实用的内置函数,用于将多个可迭代对象中对应的元素打包成元组,然后返回由这些元组组成的迭代器。
1. 基本语法和功能
语法
python
zip(iterable1, iterable2, ..., iterableN)
基本功能
python
# 将两个列表的对应元素配对 names = ["Alice", "Bob", "Charlie"] ages = [25, 30, 35] zipped = zip(names, ages) print(list(zipped)) # [('Alice', 25), ('Bob', 30), ('Charlie', 35)] # 可以处理多个可迭代对象 cities = ["New York", "London", "Tokyo"] zipped = zip(names, ages, cities) print(list(zipped)) # [('Alice', 25, 'New York'), ('Bob', 30, 'London'), ('Charlie', 35, 'Tokyo')]
2. 不同长度的可迭代对象处理
python
# 当可迭代对象长度不同时,以最短的为准 names = ["Alice", "Bob", "Charlie", "David"] ages = [25, 30] # 只有两个元素 zipped = zip(names, ages) print(list(zipped)) # [('Alice', 25), ('Bob', 30)] - 只取前两个 # 使用 itertools.zip_longest() 可以以最长的为准 from itertools import zip_longest zipped_long = zip_longest(names, ages, fillvalue="未知") print(list(zipped_long)) # [('Alice', 25), ('Bob', 30), ('Charlie', '未知'), ('David', '未知')]
3. 常见使用场景
场景1:并行迭代多个列表
python
names = ["张三", "李四", "王五"] scores = [85, 92, 78] subjects = ["数学", "英语", "物理"] for name, score, subject in zip(names, scores, subjects): print(f"{name}的{subject}成绩是:{score}分") # 输出: # 张三的数学成绩是:85分 # 李四的英语成绩是:92分 # 王五的物理成绩是:78分
场景2:创建字典
python
keys = ["name", "age", "city"] values = ["Alice", 25, "New York"] person_dict = dict(zip(keys, values)) print(person_dict) # {'name': 'Alice', 'age': 25, 'city': 'New York'} # 从两个列表创建字典 fruits = ["apple", "banana", "cherry"] prices = [1.2, 0.8, 2.5] fruit_prices = dict(zip(fruits, prices)) print(fruit_prices) # {'apple': 1.2, 'banana': 0.8, 'cherry': 2.5}
场景3:矩阵转置
python
# 二维列表转置 matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ] transposed = list(zip(*matrix)) print(transposed) # [(1, 4, 7), (2, 5, 8), (3, 6, 9)] # 转置后再转回列表形式 transposed_list = [list(row) for row in transposed] print(transposed_list) # [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
场景4:数据分组处理
python
# 将数据分成多个组 data = [1, 2, 3, 4, 5, 6, 7, 8, 9] group_size = 3 groups = list(zip(*[iter(data)] * group_size)) print(groups) # [(1, 2, 3), (4, 5, 6), (7, 8, 9)] # 如果数据不能整除,可以使用 itertools.zip_longest from itertools import zip_longest data = [1, 2, 3, 4, 5, 6, 7] groups = list(zip_longest(*[iter(data)] * 3, fillvalue=None)) print(groups) # [(1, 2, 3), (4, 5, 6), (7, None, None)]
4. 与 *
操作符配合使用(解包)
python
# 解包已压缩的数据 zipped_data = [('Alice', 25), ('Bob', 30), ('Charlie', 35)] names, ages = zip(*zipped_data) print(names) # ('Alice', 'Bob', 'Charlie') print(ages) # (25, 30, 35) # 实际应用:分离数据 students = [ ("张三", 85, "数学"), ("李四", 92, "英语"), ("王五", 78, "物理") ] names, scores, subjects = zip(*students) print(f"姓名: {names}") # 姓名: ('张三', '李四', '王五') print(f"成绩: {scores}") # 成绩: (85, 92, 78) print(f"科目: {subjects}") # 科目: ('数学', '英语', '物理')
5. 在列表推导式中的应用
python
# 使用 zip() 进行复杂计算 list1 = [1, 2, 3, 4] list2 = [10, 20, 30, 40] # 对应元素相加 result = [x + y for x, y in zip(list1, list2)] print(result) # [11, 22, 33, 44] # 对应元素相乘 result = [x * y for x, y in zip(list1, list2)] print(result) # [10, 40, 90, 160] # 条件筛选 result = [x for x, y in zip(list1, list2) if y > 15] print(result) # [2, 3, 4] - 只取 list2 中大于15的对应元素
6. 处理文件数据
python
# 读取CSV文件并处理(示例) # 假设有一个 students.csv 文件: # name,age,score # Alice,25,85 # Bob,30,92 # Charlie,35,78 # 模拟读取CSV文件 lines = [ "name,age,score", "Alice,25,85", "Bob,30,92", "Charlie,35,78" ] # 获取标题行 headers = lines[0].split(',') print(headers) # ['name', 'age', 'score'] # 处理数据行 data = [] for line in lines[1:]: values = line.split(',') data.append(values) print(data) # [['Alice', '25', '85'], ['Bob', '30', '92'], ['Charlie', '35', '78']] # 使用 zip() 创建字典列表 students = [] for row in data: student = dict(zip(headers, row)) students.append(student) print(students) # [{'name': 'Alice', 'age': '25', 'score': '85'}, # {'name': 'Bob', 'age': '30', 'score': '92'}, # {'name': 'Charlie', 'age': '35', 'score': '78'}]
7. 与 enumerate()
结合使用
python
names = ["Alice", "Bob", "Charlie"] scores = [85, 92, 78] # 同时获取索引和对应的元素 for i, (name, score) in enumerate(zip(names, scores)): print(f"第{i+1}个学生: {name}, 成绩: {score}") # 输出: # 第1个学生: Alice, 成绩: 85 # 第2个学生: Bob, 成绩: 92 # 第3个学生: Charlie, 成绩: 78
8. 性能考虑和注意事项
内存效率
python
# zip() 返回的是迭代器,节省内存 large_list1 = range(1000000) large_list2 = range(1000000) zipped = zip(large_list1, large_list2) # 不会立即创建所有元组 print(zipped) # <zip object at 0x...> # 只有在需要时才计算 first_few = list(zipped)[:5] # 只计算前5个 print(first_few) # [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
注意事项
python
# 1. zip() 返回的是迭代器,只能遍历一次 zipped = zip([1, 2, 3], ['a', 'b', 'c']) first_pass = list(zipped) # [(1, 'a'), (2, 'b'), (3, 'c')] second_pass = list(zipped) # [] - 已经耗尽 # 2. 如果需要多次使用,可以转换为列表 zipped_list = list(zip([1, 2, 3], ['a', 'b', 'c'])) print(zipped_list) # [(1, 'a'), (2, 'b'), (3, 'c')] print(zipped_list) # [(1, 'a'), (2, 'b'), (3, 'c')] - 可以多次使用 # 3. 空的可迭代对象 empty_zip = zip([], []) print(list(empty_zip)) # [] # 4. 单个可迭代对象 single_zip = zip([1, 2, 3]) print(list(single_zip)) # [(1,), (2,), (3,)]
9. 实际项目中的应用示例
示例1:学生成绩处理
python
def calculate_grades(students, scores, weights): """计算加权平均分""" weighted_scores = [] for student, score_list, weight_list in zip(students, scores, weights): total = sum(s * w for s, w in zip(score_list, weight_list)) weighted_scores.append((student, total)) return weighted_scores # 使用示例 students = ["张三", "李四"] scores = [[85, 90, 78], [92, 88, 95]] # 各科成绩 weights = [[0.3, 0.4, 0.3], [0.3, 0.4, 0.3]] # 各科权重 results = calculate_grades(students, scores, weights) for student, score in results: print(f"{student}的加权平均分: {score:.2f}") # 输出: # 张三的加权平均分: 84.90 # 李四的加权平均分: 91.90
示例2:数据验证
python
def validate_data(required_fields, input_data): """验证输入数据是否包含所有必需字段""" missing_fields = [] for field, value in zip(required_fields, input_data): if not value: missing_fields.append(field) return missing_fields # 使用示例 required = ["username", "email", "password"] user_input = ["john_doe", "", "secret123"] # 邮箱为空 missing = validate_data(required, user_input) if missing: print(f"缺少必填字段: {missing}") # 缺少必填字段: ['email'] else: print("所有字段都已填写")
总结
zip()
函数是 Python 中非常强大的工具,主要用途包括:
并行迭代:同时遍历多个可迭代对象
数据配对:将相关数据组合在一起
字典创建:从两个列表快速创建字典
矩阵转置:处理二维数据
数据分组:将数据分成指定大小的组
优点:
内存高效(返回迭代器)
代码简洁易读
支持任意数量的可迭代对象
注意事项:
迭代器只能使用一次
以最短的可迭代对象为准
需要时可以使用
itertools.zip_longest()
掌握 zip()
函数可以让你写出更加 Pythonic 和高效的代码!