编程语言研究书库

输入与输出 — 写出你的第一个程序

输入与输出 — 写出你的第一个程序

这一章讲一件事:让程序跟你说话。 你学两个函数——print() 负责「说」, input() 负责「听」——再把它们拼成一个能对话的小程序。 顺带你会碰到写代码的头号小妖怪:引号怎么配对。这一章把它彻底解决。

1. 这一章在全书链条里的位置

第 01 章解决了「代码写在哪儿」,这一章解决「代码怎么跟世界打交道」。 输入和输出(合称 I/O)是程序的定义性动作:程序就是「读进一些东西, 算一算,吐出一些东西」的循环,这一章先把「读」和「吐」两个口打通, 计算部分从下一章的变量开始。

2. 顶层全景:三个机制,一张图

  print(值)          → 把值显示到屏幕上,值可以是字符串,也可以一次好几个(逗号隔开)
  input('提示语')    → 屏幕显示提示语,程序停住等你键盘输入,你按回车后它把你的输入当字符串交回来
  print(..., input(...)) → 两个函数可以套在一起:input 先执行,把收到的字符串交给外面的 print

  图说:两个函数各管一个方向,套起来就是一问答。

3. 核心原理一:print() — 程序的嘴

print() 是 Python 的内建函数(built-in function:语言自带、不用自己写 也不装任何东西就能用的函数)。原书给它的定义很短:把一个值输出到屏幕上1。 写法是 print(值),括号里是你想显示的东西2。

你的第一行程序因此长这样:

print('Hello, world!') # display a message

跑这个格子,屏幕出现 Hello, world!。逐件拆2:

  • print 是函数的名字;圆括号表示「调用它」——让它真的干活,而不是只写下名字。
  • 'Hello, world!' 是一个字符串(string:一串文字,Python 里用引号包起来的都算)。 更精确地说它是字面量字符串——「字面」的意思是它写死在那儿、不会改变, 程序跑一百次它也是这串字3。
  • # display a message 是注释(comment):# 右边的一切,解释器直接跳过, 纯粹写给人看的笔记。注释不影响程序行为,但它决定三个月后的你能不能看懂 自己写的代码4。

在括号里用逗号隔开多个值,print() 会把它们挨着显示,中间自动补一个空格5:

print('Hello,', 'world!')   # 输出:Hello, world!
print('What', 'a', 'wonderful', 'world!')  # 输出:What a wonderful world!

注意书上特意点破的一个细节:第一个例子里第一个逗号在引号里面,属于字符串本身; 第二个逗号在引号外面,是分隔两个值的记号5。同样一个符号,位置不同身份不同—— 这在编程里是常态,现在先混个脸熟。

4. 核心原理二:引号 — 字符串的头号小妖怪

字符串必须用引号包起来。Python 给你三种包法,这一章全部讲透6。

单引号与双引号:任选,但要配对

'Hello, world!' 和 "Hello, world!" 完全等价,输出一模一样7。 那为什么要给两种?为了让你能在字符串里再放引号7:

你想输出的内容直接写会怎样两种解法
It's a beautiful day!写成 'It's ...' 时,Python 读到第二个 ' 就以为字符串结束了,后面全乱 → 语法错误① 换双引号包外面:"It's a beautiful day!" ② 转义:'It\'s a beautiful day!'
He said, "Hello, world!"写成 "He said "No!"" 时同理,第二个 " 把字符串提前掐断 → 语法错误① 换单引号包外面:'He said "No!"' ② 转义:"He said \"No!\""

转义(escaping)是上面表格里反复出现的那个词,值得正式认识: 在字符前面加一个反斜杠 \,就是在告诉 Python「下一个字符按它本来的样子算, 别按它的特殊身份算」——所以 \' 是一个真的单引号字符,而不是「字符串到此结束」的记号8。

书里给的经验法则:平时用单引号包字符串——这是 Python 圈的习惯写法; 只有字符串内容本身含单引号时,才改用双引号或转义9。

三引号:多行字符串与多行注释

用 ''' 或 """ 包起来,就是三引号字符串。它有两个独门用途10:

  1. 装多行文字,而且原样保留换行。print('''This is a multiline string''') 会真的分三行显示。
  2. 内容里随便套单双引号都不用转义:'''She said: "We're good!"''' 一点不慌。

同一个记号还有第二份兼职:三引号括起来的内容如果不交给任何函数, 它就是一段多行注释——解释器照样跳过,用来写跨好几行的说明文字11。

5. 核心原理三:input() — 程序的耳朵

print() 只能自说自话。想让程序听你说,用 input(): 它也是内建函数,作用是「读用户输入,把输入作为字符串返回」12。

input('What is your name?')

运行后,屏幕上出现提示语 What is your name?,光标停在那里等; 你键盘敲 Neo 再按回车,这个格子就把 'Neo' 交出来13。

括号里的 'What is your name?' 叫参数(argument):你交给函数用的那个值。 对 input() 来说,这个参数的内容会被显示出来当提示语,告诉你它想让你输入什么14。

一条会咬人的规则:input() 永远返回字符串,哪怕用户敲的是数字。 用户敲 18,交回来的也是 '18' 这串字符,不是数十八。这一条现在听着抽象, 下一章「变量」和第 3 章的数据类型转换会回来收拾它——先记住「敲什么都是字符串」15。

主线例子:一个完整的问候程序

把这一章的机制全部串起来,走一遍:

print('Hello,', input('What is your name? '), '!')

逐帧回放(你敲的回答以 Neo 为例):

  第 1 步 程序从外层 print 开始,发现第一个参数还没着落
  第 2 步 内层 input('What is your name? ') 先执行 → 屏幕显示:What is your name?
  第 3 步 你敲 Neo,按回车 → input 交出字符串 'Neo'
  第 4 步 print 收到全部三个参数:'Hello,'、'Neo'、'!'
  第 5 步 屏幕输出:Hello, Neo !

  图说:函数套函数时,总是最内层先执行——像先系鞋带再出门。
  那个输出里 Neo 和 ! 之间多空格,是因为逗号分隔会补空格;原书演示里就是这么显示的[^16]。

(输入 Neo 是演示用例,来自原书练习题的示例。)

再升级一版,问两次:

print(input('What is your first name? '),
      input('What is your last name?'),
      'is awesome!')

跑起来是:先问名(答 Thomas),再问姓(答 Anderson), 最后输出 Thomas Anderson is awesome!16——两个 input 按从左到右的顺序 依次执行,每个都把「等用户按回车」这件事做完才轮到下一个。

一个书里没有答案的小问题值得当场说清:如果用户什么都不敲直接按回车, input() 照样交差——交回来的是空字符串 ''(一对引号中间什么都没有), 程序不会报错也不会停住17。所以「用户可能乱输入」是真实程序必须考虑的事, 这一章先不展开,但要把这个意识种下。

6. 报错是程序在跟你说话

这一章第一次正面遇到报错。写 print('I'm fine.') 时,解释器回你一大段:

SyntaxError: unterminated string literal

别怕,拆开读:SyntaxError = 语法错误,「句子结构不合规矩」; unterminated string literal = 「有一个字符串没有正确的终止」—— 就是那个提前出现的 ' 把字符串拦腰掐断了18。

报错不是失败,是解释器在用最笨但最诚实的方式告诉你它把代码读岔在哪儿。 养成习惯:先读最后一行的错误类别,再回头看它指的那一行。 这一章遇到的两种报错都长这样,诱因都是引号没配对19。

7. 书上的练习长什么样:四道题走一遍

这一章的练习题都很短,但每道都对应一个具体的小机关。走一遍,等于把前面三节 再考一次自己20:

第 1 题(引号切换): 用双引号打印 Don't worry, be happy!。 机关:内容里有单引号,外面就用双引号包。print("Don't worry, be happy!")20。

第 2 题(转义): 同一句话,改用转义写。 机关:外面换回单引号,里面的 ' 前面加 \。print('Don\'t worry, be happy!')20。 两题输出一模一样——再次印证「单双引号与转义只是包法不同,包进去的内容不变」。

第 3、4 题(反过来): 打印带双引号的 '"Yes! I promise!"',分别用单引号包、 用转义写。机关与上面镜像20。

第 5 题(多行): 用一个 print() 打出四句诗:

This
is
a
poem

机关:三引号。print('''This\nis\na\npoem\n''') 一次装下所有换行21。 这题考的不是新知识点,而是「看到多行需求,脑子里自动弹出三引号」的条件反射—— 这个反射值得练到不假思索。

判断(我们的,不是书里的): 这四道题的安排暗藏一个挺好的顺序: 先练「换引号包」,再练「转义」,再练「三引号」——难度其实递减, 但暴露的犯错点各不相同(配对错误、反斜杠位置、换行保留)。 如果你教别人,照这个顺序出题;如果自己练,把每题的两个解法都写一遍, 「同一句话的两种写法」正是引号规则的最小完备集。 如果错,会错在: 转义写法在真实项目里越来越少见(f-string 和格式化 字符串普及之后),练它的主要价值变成了「读懂老代码」,而不是「写新代码」。

8. 常见踩坑速查(这一章的报错全在这了)

把全章的坑收进一张表,撞墙时先查它22:

你写的你会看到的原因修法
print('I'm fine.')SyntaxError: unterminated string literal字符串里的 ' 被当成结束引号外面换双引号,或写 \'
print("He said "No!"")SyntaxError: invalid syntax. Perhaps you forgot a comma?同上,双引号版外面换单引号,或写 \"
print('Hello, world!)SyntaxError: unterminated string literal(同类)少写结尾引号配对检查
print('Python' '3.12')(漏逗号)输出 Python3.12——不报错,但不是你想要的相邻字符串被 Python 自动拼接两个参数之间加逗号

最后一行那个「不报错但结果不对」的坑书上没讲,我们补在这里:它涉及 Python 的一个 默认行为(相邻字符串自动相接),但入门阶段你只需要知道——少了逗号不一定报错, 所以更要盯着输出看。

判断(我们的,不是书里的): 新人对报错的恐惧,一半来自「以为自己搞砸了大问题」。 这一章级别的报错全部可以翻译成一句人话:引号没配成对。 记住这个翻译,报错就从「红色恐怖」降级成「排字检查」。 如果错,会错在: 真实项目里 SyntaxError 的原因远不止引号(缩进、括号、 关键字拼错都触发同一类报错)——这一章的翻译只覆盖引号家族,别外推。

9. 作者的判断与证据

  • 「单引号是 Python 圈的默认写法」——这是风格约定(业界通行的习惯,不是语言强制), 书里明说推荐单引号的理由是常见、好读、遇到双引号内容时不用转义9。
  • 练习题的设计哲学写在练习区的开头:先自己死磕再看答案,而且「书上的答案不是唯一 正确答案」23——这是把练习当体检,不是当临摹。
  • 每章末尾的「Interact with GenAI」给了一组向 AI 提问的模板(「print() 是干什么的? input 返回什么类型?」)24,这是本书贯穿的特色设施,后面每章我们都会交代它的用途, 但不再复述具体提示词——它们的价值是引导提问,不是答案本身。

10. 边界与局限

  • input() 只认字符串。 想拿到数字要做类型转换——第 03 章才讲。 所以如果现在你想写「问年龄再加一」,会撞墙:'18' + 1 直接报错。 这堵墙是书故意留的,别怀疑自己。
  • 打印格式能精细控制吗? 逗号补空格是默认行为;想不补、想换行符、 想控制小数位数,print() 还有别的参数,本书到第 05 章字符串格式化才展开。
  • 没有讲文件读写。 「输入」在这里只指键盘;从文件读、往文件写要到很后面的内容才出现, 本书作为入门书干脆没碰——读到这里你要心里有数:真正的程序大多跟文件打交道。
  • print() 和 input() 只是门面。 它们背后那套「函数怎么定义、参数怎么传、 返回值怎么接」的完整机制,这本书放到第 09 章才拆。现在你可以先用得欢, 但遇到「为什么有的括号里有引号、有的没有」这类问题,答案是「第 09 章会讲」, 而不是「语法规定如此」——每处写法背后都有机制,只是还没轮到它登场。

11. 可带走的

  1. print(值) 显示值;多个值用逗号隔开,中间自动补空格5。
  2. 字符串用引号包;单双引号等价,推荐单引号;字符串里有引号就换另一种包或加 \ 转义78。
  3. '''三引号''' 装多行文字、装任意引号;单独摆着就是多行注释1011。
  4. # 右边是注释,解释器跳过,是写给三个月后的自己看的4。
  5. input(提示语) 显示提示、等你输入、把输入作为字符串交回来1215。
  6. 函数套函数,最内层先执行25。
  7. SyntaxError 先读最后一行,再看它指的那一行18。
  8. 书上的练习答案不是唯一解;先死磕再看答案,卡住时可以拿章末的 GenAI 提示当台阶,但别直接要代码2324。

12. 原文地图

主题原书章原文位置
print() 与第一行程序CHAPTER 2: Input and Outputtext/11-ch02-chapter-2-input-and-output.txt:13(搜「display a message」) · text/11-ch02-chapter-2-input-and-output.txt:17(搜「outputs text to the screen」)
字符串字面量与注释同上text/11-ch02-chapter-2-input-and-output.txt:21(搜「sequence of characters」) · text/11-ch02-chapter-2-input-and-output.txt:28(搜「in-line comment」)
单双引号与转义同上text/11-ch02-chapter-2-input-and-output.txt:58(搜「either single quotation mark」) · text/11-ch02-chapter-2-input-and-output.txt:71(搜「Escaping allows you」)
推荐单引号的理由同上text/11-ch02-chapter-2-input-and-output.txt:66(搜「generally recommended」)
三引号:多行字符串与多行注释同上text/11-ch02-chapter-2-input-and-output.txt:141(搜「multiline strings」) · text/11-ch02-chapter-2-input-and-output.txt:146(搜「multiline comments」)
print 打印多值与逗号空格同上text/11-ch02-chapter-2-input-and-output.txt:233(搜「separated by a space」)
input() 与提示语、参数同上text/11-ch02-chapter-2-input-and-output.txt:301(搜「return it as a string」) · text/11-ch02-chapter-2-input-and-output.txt:303(搜「displayed as a prompt」)
input 永远返回字符串同上text/11-ch02-chapter-2-input-and-output.txt:328(搜「always returns a string」)
函数套函数的演示同上text/11-ch02-chapter-2-input-and-output.txt:335(搜「Hello,', input」) · text/11-ch02-chapter-2-input-and-output.txt:345(搜「first name」)
两种语法错误的实例同上text/11-ch02-chapter-2-input-and-output.txt:86(搜「unterminated string literal」) · text/11-ch02-chapter-2-input-and-output.txt:104(搜「invalid syntax」)
练习哲学与 GenAI 提示同上text/11-ch02-chapter-2-input-and-output.txt:40(搜「not the only correct ones」) · text/11-ch02-chapter-2-input-and-output.txt:276(搜「purpose of the print()」)

Footnotes

  1. 出处:「CHAPTER 2: Input and Output」第 17 段(text/11-ch02-chapter-2-input-and-output.txt:17,搜「outputs text to the screen」)。原文:「The print() function is a built-in Python function that outputs text to the screen.」 ↩

  2. 出处:「CHAPTER 2: Input and Output」第 13–27 段(text/11-ch02-chapter-2-input-and-output.txt:13,搜「display a message」;:26,搜「syntax for the print() function」)。 ↩ ↩2

  3. 出处:「CHAPTER 2: Input and Output」第 21–25 段(text/11-ch02-chapter-2-input-and-output.txt:23,搜「literal string」)。原文:「The string 'Hello, world!' is a literal string, meaning it's a fixed sequence of characters that doesn't change.」 ↩

  4. 出处:「CHAPTER 2: Input and Output」第 28–34 段(text/11-ch02-chapter-2-input-and-output.txt:28,搜「to the right of the #」)。注释被解释器忽略、用于增加可读性,原文明写。 ↩ ↩2

  5. 出处:「CHAPTER 2: Input and Output」第 230–241 段(text/11-ch02-chapter-2-input-and-output.txt:232,搜「separate values with a comma」;:240,搜「the first comma is within」)。「两个逗号身份不同」这个提醒是原书第 240 段的原意。 ↩ ↩2 ↩3

  6. 出处:「CHAPTER 2: Input and Output」第 58–75 段(单双引号)与第 141–149 段(三引号),各节标题即原书小节名(SINGLE OR DOUBLE / TRIPLE QUOTATIONS)。 ↩

  7. 出处:「CHAPTER 2: Input and Output」第 58–65 段(text/11-ch02-chapter-2-input-and-output.txt:58,搜「either single quotation mark」;:62,搜「contain quotations」)。两种引号等价、为方便内含引号而并存,均为原文明写。 ↩ ↩2 ↩3

  8. 出处:「CHAPTER 2: Input and Output」第 71–73 段(text/11-ch02-chapter-2-input-and-output.txt:71,搜「include special characters」)。转义的定义逐字依据原文。 ↩ ↩2

  9. 出处:「CHAPTER 2: Input and Output」第 66–70 段(text/11-ch02-chapter-2-input-and-output.txt:67,搜「use single quotes for defining strings」)。原文给出两个理由:更常见、更好读;以及字符串含双引号时不用转义。 ↩ ↩2

  10. 出处:「CHAPTER 2: Input and Output」第 141–145 段(text/11-ch02-chapter-2-input-and-output.txt:141,搜「define multiline strings」;:142,搜「span multiple lines」;:145,搜「don't need to escape」)。 ↩ ↩2

  11. 出处:「CHAPTER 2: Input and Output」第 146–149 段(text/11-ch02-chapter-2-input-and-output.txt:146,搜「define multiline comments」)。「三引号不交给任何函数就是注释」是对原文「To define a multiline comment, you simply enclose your text in triple quotations」的转述。 ↩ ↩2

  12. 出处:「CHAPTER 2: Input and Output」第 300–301 段(text/11-ch02-chapter-2-input-and-output.txt:301,搜「return it as a string」;:301,搜「return it as a string」)。 ↩ ↩2

  13. 出处:「CHAPTER 2: Input and Output」第 294–298 段(text/11-ch02-chapter-2-input-and-output.txt:294,搜「What is your name?」)。演示中输入 Neo 后的回显 {"type":"string"} 是 Jupyter 环境对返回值类型的标注,说明交回来的是字符串。 ↩

  14. 出处:「CHAPTER 2: Input and Output」第 302–307 段(text/11-ch02-chapter-2-input-and-output.txt:302,搜「an argument that the input() function takes」;:303,搜「displayed as a prompt」)。「参数」的中文解释是我们补的;原文称 argument。 ↩

  15. 出处:「CHAPTER 2: Input and Output」第 326–329 段(text/11-ch02-chapter-2-input-and-output.txt:328,搜「Even if the user enters a number」)。原文:「Even if the user enters a number, it will be returned as a string.」 ↩ ↩2

  16. 出处:「CHAPTER 2: Input and Output」第 345–351 段(text/11-ch02-chapter-2-input-and-output.txt:345,搜「first name」)。Thomas / Anderson 的例子与原书逐字一致。 ↩

  17. 补充(不在书里,来自通用知识):input() 在用户直接按回车时返回空字符串,Python 官方文档对 input() 的描述是「read a line from input」(读取输入中的一行),行可以为空。原书第 387 段(text/11-ch02-chapter-2-input-and-output.txt:387,搜「presses Enter without entering anything」)把这个问题列进了 GenAI 互动提示,但没有给出答案。 ↩

  18. 出处:「CHAPTER 2: Input and Output」第 83–86 段(text/11-ch02-chapter-2-input-and-output.txt:86,搜「unterminated string literal」)。报错原文是 SyntaxError: unterminated string literal (detected at line 2),且错误信息用 ^ 指向出错位置(第 85 段)。 ↩ ↩2

  19. 出处:「CHAPTER 2: Input and Output」第 98–104 段(text/11-ch02-chapter-2-input-and-output.txt:104,搜「Perhaps you forgot a comma」)。第二种报错是 SyntaxError: invalid syntax. Perhaps you forgot a comma?,诱因同为引号抢占。 ↩

  20. 出处:「CHAPTER 2: Input and Output」第 116–136 段(text/11-ch02-chapter-2-input-and-output.txt:117,搜「Don't worry, be happy」)。四道引号练习题及其双解法见原文练习区。 ↩ ↩2 ↩3 ↩4

  21. 出处:「CHAPTER 2: Input and Output」第 178–194 段(text/11-ch02-chapter-2-input-and-output.txt:185,搜「This」)。诗题及其三引号解法见原文;「用一次 print 打多行」是原题的要求(第 179 段)。 ↩

  22. 出处:「CHAPTER 2: Input and Output」第 80–114 段(text/11-ch02-chapter-2-input-and-output.txt:86,搜「unterminated string literal」;:104,搜「Perhaps you forgot a comma」)。表中前三个坑均出自原书演示;「相邻字符串自动拼接」不在原书,标为补充。 ↩

  23. 出处:「CHAPTER 2: Input and Output」第 37–41 段(text/11-ch02-chapter-2-input-and-output.txt:38,搜「Struggling with the tasks」;:40,搜「not the only correct ones」)。 ↩ ↩2

  24. 出处:「CHAPTER 2: Input and Output」第 255–285 段(text/11-ch02-chapter-2-input-and-output.txt:276,搜「purpose of the print() function」)。练习区与 GenAI 提示的完整清单见原文,此处只摘主题。 ↩ ↩2

  25. 出处:「CHAPTER 2: Input and Output」第 335–338 段(text/11-ch02-chapter-2-input-and-output.txt:335,搜「Hello,', input('What is your name?」)。原书演示输出为 Hello, Neo !,Neo 与 ! 之间确有空格——这是逗号补空格的直接证据。 ↩

On this page