(十二)批量输入、map 与迭代器
1. 先拆开写出输入转换
任务:一行输入三个整数,输出它们的和。先观察每个中间结果:
# 先读到整行字符串,再按空白拆成三个字符串项。
line = input()
parts = line.split()
# 每一项单独转成整数,再交给后续计算。
a = int(parts[0])
b = int(parts[1])
c = int(parts[2])
print(a + b + c)输入 10 20 30,结果为 60。到这里还没有新语法,只有字符串切分、下标访问与整数转换。转换项数增多时,可以先把重复动作写成循环:
# 遍历切分结果,逐项转换并加入新的整数列表。
parts = input().split()
numbers = []
for part in parts:
numbers.append(int(part))
a, b, c = numbers
print(a + b + c)2. 把转换动作交给 map
map 接收“要执行的函数”和“要处理的数据”。int 不加括号时代表这个转换工具本身;int("10") 则表示立刻调用它,得到整数 10。
# map 把 int 作为转换动作保存,拆包时再逐项读取并转换。
a, b, c = map(int, input().split())
print(a + b + c)把这一行从里面向外读:
input()返回"10 20 30"。.split()得到['10', '20', '30']。map(int, ...)建立逐项转换的迭代器。- 拆包读取迭代器:取
"10"时得到10,随后得到20和30;数量与接收位置匹配后,把它们绑定给a、b、c。
这里必须写 map(int, ...)。若写成 map(int(input().split())),内层会先尝试把整个字符串列表交给 int,在进行逐项转换前就报错。逗号把“转换工具”与“待处理数据”分成两个参数。
3. map 返回的对象会被逐项消耗
# 建立 map 时还没有把每一项转换成整数。
values = map(int, ["10", "20", "30"])
# next 读取下一项,返回本次转换得到的整数。
print(next(values))
# list 继续读取剩余项,直到没有更多项。
print(list(values))
# 同一迭代器已经走到末尾,再次收集得到空列表。
print(list(values))输出 10、[20, 30]、[]。可迭代对象是“能够逐项提供值”的数据来源,迭代器还保存“已经读到哪里”的进度。map 本身就是一个迭代器;列表可以再次从头遍历,同一个 map 不会自动回到开头。
需要反复使用转换结果时,先收集为列表,例如 numbers = list(map(int, input().split()))。这一步会读完当前输入中的所有项并保存整数。next(values, "结束") 则可以在没有更多项时返回给定的默认值。
输入少一项或多一项时,固定数量的拆包会报 ValueError;其中一项是 "abc" 时,int 转换也会报 ValueError。这两个失败分别发生在分配数量与转换内容的步骤,后面学习异常时会给它们安排恢复和重试。map 返回迭代器的行为可查 内置函数文档。