zip() - 打包函数
将多个可迭代对象打包成元组的迭代器
zip() - 打包函数
📝 概述
zip() 是 Python 中的内置函数,用于将多个可迭代对象的对应元素打包成元组。它返回一个迭代器,可以同时遍历多个序列,在数据处理和并行迭代中非常有用。
🎯 学习目标
- 掌握 zip()函数的基本用法
- 理解 zip()的行为特点和限制
- 学会使用 zip()进行数据组合和转换
- 了解 zip()在实际编程中的应用场景
📋 前置知识
- Python 基本语法
- 可迭代对象的概念
- 元组和列表的基本操作
- for 循环和元组解包
🔍 详细内容
基本概念
zip() 函数接受多个可迭代对象作为参数,返回一个迭代器。该迭代器生成元组,每个元组包含来自各个可迭代对象的对应位置的元素。当最短的可迭代对象耗尽时,迭代停止。
语法格式
zip(*iterables)
参数说明
| 参数名 | 类型 | 必需 | 默认值 | 说明 |
|---|---|---|---|---|
| *iterables | iterable | 否 | 无 | 零个或多个可迭代对象 |
返回值
| 类型 | 说明 |
|---|---|
| zip | 迭代器,产生元组序列 |
💡 实际应用
基础用法
## 基本打包
names = ["张三", "李四", "王五"]
ages = [25, 30, 35]
for name, age in zip(names, ages):
print(f"{name}今年{age}岁")
## 输出:
## 张三今年 25 岁
## 李四今年 30 岁
## 王五今年 35 岁
## 转换为列表查看结果
print(list(zip(names, ages))) # [('张三', 25), ('李四', 30), ('王五', 35)]
## 三个列表的组合
names = ["张三", "李四", "王五"]
ages = [25, 30, 35]
cities = ["北京", "上海", "广州"]
for name, age, city in zip(names, ages, cities):
print(f"{name},{age}岁,来自{city}")
## 空参数调用
print(list(zip())) # []
## 单个参数
numbers = [1, 2, 3]
print(list(zip(numbers))) # [(1,), (2,), (3,)]
高级用法
## 长度不同的序列
list1 = [1, 2, 3, 4, 5]
list2 = ['a', 'b', 'c']
print(list(zip(list1, list2))) # [(1, 'a'), (2, 'b'), (3, 'c')]
## 注意:较长的序列中的额外元素被忽略
## 字符串的 zip
word1 = "hello"
word2 = "world"
for char1, char2 in zip(word1, word2):
print(f"{char1}-{char2}")
## 输出: h-w, e-o, l-r, l-l, o-d
## 解包操作(转置)
matrix = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
print(list(zip(*matrix))) # [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
## 创建字典
keys = ['name', 'age', 'city']
values = ['张三', 25, '北京']
person = dict(zip(keys, values))
print(person) # {'name': '张三', 'age': 25, 'city': '北京'}
## 并行处理多个列表
numbers1 = [1, 2, 3, 4]
numbers2 = [10, 20, 30, 40]
sums = [x + y for x, y in zip(numbers1, numbers2)]
print(sums) # [11, 22, 33, 44]
实际案例
## 数据表格处理
def create_table(headers, *rows):
"""创建简单的数据表格"""
# # 打印表头
print("|", end="")
for header in headers:
print(f" {header:^10} |", end="")
print()
# # 打印分隔线
print("|" + "-" * (12 * len(headers) + 1) + "|")
# # 打印数据行
for row in rows:
print("|", end="")
for item in row:
print(f" {str(item):^10} |", end="")
print()
## 使用示例
headers = ["姓名", "年龄", "城市"]
row1 = ["张三", 25, "北京"]
row2 = ["李四", 30, "上海"]
row3 = ["王五", 35, "广州"]
create_table(headers, row1, row2, row3)
## 数据统计分析
def analyze_scores(subjects, scores):
"""分析各科成绩"""
print("成绩分析报告:")
print("-" * 30)
total_score = 0
for subject, score in zip(subjects, scores):
print(f"{subject}: {score}分")
total_score += score
average = total_score / len(scores)
print("-" * 30)
print(f"总分: {total_score}分")
print(f"平均分: {average:.2f}分")
return total_score, average
## 使用示例
subjects = ["语文", "数学", "英语", "物理", "化学"]
scores = [85, 92, 78, 88, 90]
analyze_scores(subjects, scores)
## 文件对比
def compare_files(file1_lines, file2_lines):
"""逐行对比两个文件"""
differences = []
for line_num, (line1, line2) in enumerate(zip(file1_lines, file2_lines), 1):
if line1.strip() != line2.strip():
differences.append({
'line': line_num,
'file1': line1.strip(),
'file2': line2.strip()
})
if differences:
print(f"发现 {len(differences)} 处差异:")
for diff in differences:
print(f"第{diff['line']}行:")
print(f" 文件 1: {diff['file1']}")
print(f" 文件 2: {diff['file2']}")
else:
print("两个文件内容相同")
return differences
## 坐标变换
def transform_coordinates(x_coords, y_coords, dx=0, dy=0):
"""坐标平移变换"""
transformed = []
for x, y in zip(x_coords, y_coords):
new_x = x + dx
new_y = y + dy
transformed.append((new_x, new_y))
return transformed
## 使用示例
original_x = [1, 2, 3, 4]
original_y = [1, 4, 9, 16]
transformed_coords = transform_coordinates(original_x, original_y, dx=10, dy=5)
print(f"原坐标: {list(zip(original_x, original_y))}")
print(f"变换后: {transformed_coords}")
## 数据验证
def validate_user_data(names, emails, ages):
"""验证用户数据"""
errors = []
for i, (name, email, age) in enumerate(zip(names, emails, ages)):
# # 验证姓名
if not name or len(name.strip()) == 0:
errors.append(f"第{i+1}行: 姓名不能为空")
# # 验证邮箱
if '@' not in email:
errors.append(f"第{i+1}行: 邮箱格式不正确")
# # 验证年龄
if not isinstance(age, int) or age < 0 or age > 150:
errors.append(f"第{i+1}行: 年龄必须是 0-150 之间的整数")
if errors:
print("数据验证失败:")
for error in errors:
print(f" - {error}")
return False
else:
print("数据验证通过")
return True
## 测试数据
test_names = ["张三", "", "王五"]
test_emails = ["zhangsan@email.com", "lisi.email.com", "wangwu@email.com"]
test_ages = [25, 30, 200]
validate_user_data(test_names, test_emails, test_ages)
⚠️ 注意事项
zip()以最短的可迭代对象为准,较长对象的多余元素会被忽略zip()返回的是迭代器,只能遍历一次- 如果需要处理不同长度的序列,考虑使用
itertools.zip_longest() - 空的 zip()调用返回空迭代器
## 长度不同的处理
from itertools import zip_longest
list1 = [1, 2, 3, 4, 5]
list2 = ['a', 'b', 'c']
## 标准 zip()会截断
print(list(zip(list1, list2))) # [(1, 'a'), (2, 'b'), (3, 'c')]
## zip_longest()会填充缺失值
print(list(zip_longest(list1, list2, fillvalue='X')))
## [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'X'), (5, 'X')]
## 迭代器特性
data1 = [1, 2, 3]
data2 = ['a', 'b', 'c']
zip_obj = zip(data1, data2)
## 第一次遍历
print("第一次:", list(zip_obj)) # [(1, 'a'), (2, 'b'), (3, 'c')]
## 第二次遍历(空结果)
print("第二次:", list(zip_obj)) # []
🔗 相关内容
📚 扩展阅读
🏷️ 标签
迭代 打包 并行 数据组合 转置
最后更新: 2024-01-15
作者: Python 文档工程师
版本: 1.0
讨论与反馈
欢迎在下方留言讨论,分享你的学习心得或提出问题。评论基于GitHub Issues,需要GitHub账号。