如何实现读取一行输入的两个数字

在编写算法题或处理外部数据流时,我们经常需要解析同一行输入的多个数据。如果在 C 语言中,我们习惯使用 scanf("%d %d", &n, &d) 来读取格式化数据。但在 Python 中,这种操作有着更具“Pythonic”风格的优雅实现方案:map()split() 的组合。

本文将深入拆解这两个底层函数的工作机制,探讨其进阶用法以及底层的迭代器特性。

一、 split():字符串分割

split() 是 Python 字符串内置的核心方法,其底层逻辑是通过遍历字符串并匹配分隔符,将长字符串切割为多个子串,最终返回一个列表

1. 基础用法:默认切分

如果不传入任何参数,split() 默认以所有空白字符(包括空格、换行符 \n、制表符 \t 等)作为分隔符,并且会自动丢弃连续的空白字符。

1
2
3
text = "  3   5 \t 7  "
result = text.split()
print(result) # 输出: ['3', '5', '7']

2. 进阶用法:自定义分隔符与切割次数

查看 Python 源码说明,split 的完整签名为 str.split(sep=None, maxsplit=-1)

  • sep (分隔符):可以指定具体的字符组合进行切割。比如处理 CSV 文件时,通常按逗号切割。
  • maxsplit (最大切割次数):限制切割的动作次数。如果设定为 1,则切了一刀之后,剩下的整个长字符串会作为列表的最后一个元素原样保留。
1
2
3
4
5
6
7
# 提取日志信息:只切分出时间,保留后面的完整内容
log_data = "2026-04-09_ERROR_System boot failed due to fan issue"

# 以 '_' 切割,但只切 2 次
parts = log_data.split('_', maxsplit=2)
print(parts)
# 输出: ['2026-04-09', 'ERROR', 'System boot failed due to fan issue']

二、 map():函数式映射与迭代器机制

map() 是 Python 的内置高阶函数。它的设计理念源自“函数式编程”,核心作用是:将指定的函数,依次作用于可迭代对象(如列表、字符串)的每一个元素上。

它的函数签名是:map(function, iterable, ...)

1. 基础转换

假设 split() 帮我们拿到了一组字符串 ['10', '20'],我们需要将其转为整型。使用 map 可以免去繁琐的 for 循环:

1
2
3
str_list = ['10', '20']
# 将 int() 函数批量应用到 str_list 的每个元素上
mapped_data = map(int, str_list)

2. 专业进阶:map 对象与惰性求值 (Lazy Evaluation)

在 Python 3 中,必须明确一个关键概念:map() 的返回值不再是一个列表,而是一个迭代器(Iterator)对象。

迭代器详情可见:什么是迭代器

如何提取迭代器里的数据?

  • 方式 A(强转列表):如果后续需要反复使用这些数据,可以使用 list() 一次性将其全部计算并存入内存。

    1
    num_list = list(map(int, ['10', '20']))
  • 方式 B(多变量解包 Unpacking):如果确切知道有几个数据,可以直接利用 Python 的解包特性赋给变量。

    1
    n, d = map(int, ['10', '20'])

三、 组合拳:执行逻辑彻底拆解

现在,我们再回过头看这句在算法题中出场率极高的代码:

1
n, d = map(int, input().split())

它在 Python 解释器中的底层执行流水线如下:

  1. input():阻塞程序,读取标准输入流中的一行数据,得到原始字符串,例如 "3 5"
  2. .split():字符串对象调用方法,按默认空白字符切割,在内存中生成临时列表 ['3', '5']
  3. map(int, ...):创建一个映射迭代器,绑定的转换规则是 int 函数,目标数据是刚才的临时列表。
  4. n, d = ...:触发解包机制,迫使 map 迭代器立刻产出数据。迭代器产出 3 赋给 n,产出 5 赋给 d,随后临时对象被 Python 的垃圾回收机制(GC)清理。