前言input()是 Python 里从键盘准确说是标准输入读一行文本的唯一内置手段。它的行为极其简单往标准输出写一段提示语等用户敲回车然后把这一行作为字符串返回。但正因为它太简单误解反而很多其中错得最普遍的一条来自 Python 2 的遗留印象——在 Python 2 里input()会把你输入的内容当成 Python 代码求值效果等同于eval(raw_input())输入11会得到整数2。Python 3 的input()对应的是 Python 2 的raw_input()永远返回字符串输入11得到的是11这五个字符。老教程里那种「输入数字不用转换」的说法在 Python 3 已经不成立。第二条常见误解是以为input()能读多行、能解析成数字、能处理逗号分隔。都不行。它一次只读一行返回类型永远是str所以「读数字」要自己int()「读列表」要自己split()而只要涉及转换就必须处理转换失败ValueError的情况。本文讲清input()的签名与返回、输入转换的套路、多行读取的不同做法以及几个真会踩的坑。一、签名与返回官方文档给出的形式是input(prompt, /)——prompt是可选参数并且带/标记表示仅位置参数不能写成input(prompt请输入)。# 适用于 Python 3.8name input(请输入你的名字)print(你好 name)行为细节行为说明提示语输出位置标准输出stdout且不带结尾换行返回值总是str换行符末尾的换行会被去掉结果里不含\n读不到数据时抛EOFError「末尾换行被去掉」意味着input()的结果通常不需要再strip()——但用户可能敲了空格那要另说。而「读不到数据」发生在输入流结束终端里按 CtrlD 或 CtrlZ时input()抛EOFError# 适用于 Python 3.8try:line input(请输入)except EOFError:print(没有读到任何输入已到文件末尾)注意input()返回的是「去掉换行后的一整行」空行是合法的直接回车得到的是空字符串不会报错。二、把字符串转成需要的类型input()只给字符串后续转换全要自己来。最常用的是转数字# 适用于 Python 3.8raw input(请输入一个整数) # 比如用户敲 42number int(raw) # 转成 intprint(number 1)用户输入不一定合法所以生产代码要给个重试循环# 适用于 Python 3.8def read_int(prompt):while True:raw input(prompt)try:return int(raw)except ValueError:print(f「{raw}」不是合法整数请重新输入。)age read_int(请输入年龄)print(f明年你 {age 1} 岁)一次读多个值标准套路是split()加map()# 适用于 Python 3.8line input(输入两个整数用空格分隔) # 比如 3 5a, b map(int, line.split())print(a b)这里用的是可迭代解包split()得到字符串列表map(int, ...)把每个元素转成整数再解包给a、b。注意如果用户输入的个数不对会抛ValueError值太多或太少字段本身不是数字也会抛ValueError所以真实程序里这两处都要兜住。三、一次一行 vs 一次读全部input()的定位是「交互式读一行」。如果输入是要整批处理的比如从文件、从管道喂进来用sys.stdin更合适需求写法结束条件交互读一行input(prompt)用户回车EOF 抛EOFError交互循环读一行while True:包里input()用EOFError或某个哨兵值跳出读完整个标准输入for line in sys.stdin:输入流结束不抛异常# 适用于 Python 3.8import systotal 0for line in sys.stdin: # 管道 / 重定向进来的每一行自带换行text line.strip() # 注意迭代出来的行是带 \n 的if not text:continuetotal int(text)print(f合计 {total})关键差别用for line in sys.stdin拿到的每一行是带末尾换行的所以要strip()而input()拿到的已经去掉换行。很多人把两种读法的行为记混。用一个哨兵值终止交互输入也是常见做法# 适用于 Python 3.8lines []while True:line input(输入内容直接回车结束)if line :breaklines.append(line)print(f共输入 {len(lines)} 行)四、实战一个带校验的小型录入程序# 适用于 Python 3.8def read_int(prompt, loNone, hiNone):读一个整数失败或超范围就重试。while True:try:value int(input(prompt))except ValueError:print(请输入整数。)continueif lo is not None and value lo:print(f不能小于 {lo}。)continueif hi is not None and value hi:print(f不能大于 {hi}。)continuereturn valuedef main():print(学生成绩录入总分 100)results []try:while True:name input(姓名直接回车结束).strip()if not name:breakscore read_int(f{name} 的分数, lo0, hi100)results.append((name, score))except EOFError:print(\n输入结束。)if not results:print(没有录入任何数据。)returnavg sum(s for _, s in results) / len(results)print(f共 {len(results)} 人平均分 {avg:.1f})if __name__ __main__:main()这段代码把本文的要点都用上了input()返回字符串、int()转换要兜ValueError、空行当终止哨兵、EOFError兜住流结束、用.strip()处理用户多打的空格。常见坑点以为 input 会自动转成数字❌n input(数字)然后n 1→TypeError: can only concatenate str (not int) to str✅n int(input(数字))并用try/except ValueError处理非法输入拿 Python 2 的行为套 Python 3❌ 期待input()「输入表达式会求值」Python 2 的行为或以为它是eval✅ Python 3 的input()恒返回str它对应 Python 2 的raw_input()对 input 的结果又 strip 一次还搞不清换行❌ 以为input()结果带\n其实已经去掉了反过来又以为sys.stdin迭代出来的行不带\n✅input()已去掉换行for line in sys.stdin的line带换行需要strip()忘了 prompt 是仅位置参数❌input(prompt姓名)→TypeError: input() takes no keyword arguments✅input(姓名)不处理 EOFError❌ 在管道里跑input()输入流一结束就抛出EOFError让程序崩掉✅ 用try/except EOFError收尾或改用for line in sys.stdin一次性解包却不校验个数❌a, b map(int, input().split())用户只输入一个数就抛ValueError: not enough values to unpack✅ 先parts input().split()判断len(parts)再解包把 eval 用在输入上❌n eval(input(数字))图省事用户输入一段代码就会被执行——eval能执行任意代码绝不能用于不可信输入✅ 明确用int()/float()/ast.literal_eval()中合适的一个绝不用eval误以为 input 能读多行❌ 让用户粘贴多行文本期望input()一次全拿到✅input()只读一行多行要用循环配合EOFError或改用sys.stdin.read()总结需求写法读一行input(提示)读整数int(input(...))配try/except ValueError读多个值a, b map(int, input().split())循环读直到结束while TrueEOFError或哨兵值读整个标准输入for line in sys.stdin:记得strip()input()只有一条铁律它永远返回字符串。剩下的所有「读数字」「读列表」「读到结束」都是在这个字符串上再做转换与循环。把三件事记住就够了——input()已去掉末尾换行、sys.stdin迭代出来的行带换行、以及转换失败要兜ValueError再用try/except EOFError处理输入流结束交互式输入就写得很稳了。