学径 LearnPath

编程语言基础

程序

把可检验的思想写成机器能够执行的形式。

讲解模式

通过本节课,你将理解:

#goal

程序 是研究计算机科学的重要工具,通过把「先做什么、再做什么、何时停止」写下来,使另一次运行、另一组数据、另一台机器,仍然得到同一套逻辑相同的结果。

编写程序,通常简写为编程。一段程序的形态可以是自然语言、流程图、数学公式等等。但在计算机中,我们通常通过写代码来编程,因为计算机更擅长理解代码。

本课用 Python 作为编程语言,运行环境是本平台的 在线 IDE。你还可以随时在页面的右上角找到它。

本次课你将编写出你的第一行程序,让它向世界问好!

hello, world!

计算机程序的起源

#hook

1840 年代,查尔斯·巴贝奇设计出了具有里程碑意义的分析机,但当时多数人仍把它想成一台更快的计算器。因为在那个年代,大部分的机器和工具都只能处理一件特定的任务。比如计算加法要用加法器,计算对数要用对数尺等等。

查尔斯·巴贝奇的分析机试验模型
查尔斯·巴贝奇分析机的运算部件试验模型,1834–1871,伦敦科学博物馆藏。来源:Wikimedia Commons / Science Museum,CC BY-SA 2.0。

巴贝奇的好友,艾达·洛夫莱斯却指出:若机器能按规则操作符号,它理论上也可以处理音乐、几何图形等等,音乐和图形本质上都是特定计算过程产生的结果。

艾达·洛夫莱斯画像
艾达·洛夫莱斯,约1840年,阿尔弗雷德·爱德华·查隆绘。来源:Wikimedia Commons / Science Museum Group,公有领域。

遗憾的是分析机的设计领先于时代太多,当时的生产工艺并不能将其制作出来。

一个世纪之后,ENIAC 用电缆和开关实现巴贝奇和艾达的理想,只需要改变线缆的连接方式,就能改变它的计算过程,从而实现不同的功能。计算机科学的故事从此正式拉开了帷幕。

宾夕法尼亚大学穆尔学院的 ENIAC
ENIAC 功能表前的操作,1946年。U. S. Army Photo。来源:Wikimedia Commons,公有领域。

那到底什么是计算过程呢?

举例来说,计算 3×4+53\times 4 + 5 时,我们将计算过程分为以下两个步骤:

  1. 先计算3与4的乘法,得到结果12
  2. 将12与5相加,得到结果17

不论这里具体的数字改成什么,比如 6×5+46\times 5 + 4 ,亦或者 52×10+152\times 10 + 1,步骤都是确定的两步:

  1. 先计算前两项的乘积
  2. 把中间结果与后一项求和

于是在数学里,通过代数的方法,将具体的数字可以写为字母符号,意思为任意数字 a×b+ca\times b + c 。类似的,使用函数符号 f(x)=a×b+c f(x) = a\times b + c 表示这个计算的过程。

在编程时,只需要将这些符号改写为机器能懂的语言,比如“线缆的连接方式”或“二进制代码”,即可让机器的功能转化为对应的计算过程。

用 0 与 1 写成的机器语言
示意图:机器以二进制编码将要执行的步骤。为本课绘制。

单凭机器,没有程序,只是一堆会通电的器件。单凭一份写在纸上的步骤,没有机器去执行,也只是一份说明书。二者合在一起,才出现现代意义上的计算:人负责提出问题和验收结果,机器负责把同一套步骤在巨大的规模上重复、精确地做完。

以天气预报为例。大气运动可以用流体力学方程来描述,卫星和地面站不断送来观测数据。没有人能在一张草稿纸上,对地球大气的每一个格子、每一个时刻手算出明天的雨带。程序把方程离散成一步步可执行的更新:读入当前状态,按规则推进一步,再推进一步。超级计算机负责把这些步骤跑完。气象员并不查看每一次内部乘法的中间值,而是在关键时刻读取:未来二十四小时的降水概率、台风路径的集合预报。

Python 编程语言

#explore-languages

如上所述,计算机真正执行的,是极其简单的电路开关游戏,人无法直接用那种粒度思考复杂的问题。于是编程语言出现了,它就像是人机之间的翻译:把接近人类问题的写法,变成机器可以运行的指令。

但是不同的编程语言,是对「要多近才算接近」、「接近什么才算接近」有着不同的理解。

在二十世纪中叶前后,诞生了一大批至今还在应用的编程语言:Fortran 面向数值与工程计算;Lisp 面向符号与表结构;C 贴近机器,用来把内存和时钟管清楚;后来的语言又分别面向网页、证明、统计与数据。

选择语言,就是选择一套抽象:哪些细节可以被隐藏起来,哪些必须写明白。没有一种语言在所有问题上都最优——正如没有一种实验仪器能同时做完所有测量。

本课选择 Python,不是因为它是「最好的语言」,而是因为它适合用来理解计算思想,又足够接近真实的科学工作。

Python 官方标志
Python 语言官方标志。设计:Tim Parkin;Python Software Foundation 商标。来源:python.org。

Python 原意为蟒蛇,其logo的样貌也是取自于此。由吉多·范罗苏姆(Guido van Rossum)在 1980 年代末开始设计,1991 年公开发布。据说这个名字来自英国喜剧《蒙提·派森的飞行马戏团》,与蟒蛇并没有关系。

Pyhton的优点非常明显,写法相对接近自然语言,标准库和科学社区提供了大量已经检验过的工具,它对运行环境要求不高,即使在浏览器中也能工作。三十多年来,已经成为了科学计算、数据处理、人工智能实验里最常见的书写工具之一。

但缺点也同样明显,Python 通常比贴近硬件的语言慢,在计算机的世界里,也许慢就是「原罪」吧。

学会Python以后,你可以在实验室用它整理观测表、拟合曲线、检查公式在边界上是否成立;开发网站,并把请求交给后台服务;进行气象、基因组、经济数据、机器学习实验等等等。

编程中的最核心的理念是抽象,即通过发明新的符号来代指一个复杂的过程。比如我们发明了 ×\times 乘法符号,来表示多个相同数字的相加。 未来你也会自己发明一些符号,但在此之前请先学习别人发明的符号,并尊重他们的使用规则。

你好世界!

#explore-program

接下来,就让我们学习和运行本课程的第一行代码。点击代码框右上角的运行按钮,便可以在我们的在线 IDE 中运行这段代码,如果一切顺利可以在结果框看到 hello, world! 这句话。

python
print('hello, world!')

这段代码中的符号是什么意思?让我们来一一看一下。

首先,第一个符号print,刚好是一个英文单词——打印。

我们刚刚说到计算机中的程序可以用于描述复杂的计算过程,对于人类来说,通常不关心里面每一个具体步骤的计算结果,我们希望机器只告诉我们其中关键步骤的结果。于是我们需要在程序中告知计算机,在什么时间把什么内容展示给人类。在计算机刚被发明的时候,现代显示器还没有被发明,只有打印机可以用于显示结果,于是命名为 print 打印。

IBM 1403 宽行打印机
IBM 1403 宽行打印机,1959 年起用于主机把计算结果印在纸上。摄影:Crisco 1492。来源:Wikimedia Commons,CC BY-SA 3.0。

在print后面紧跟着的是一对小括号(),请注意是英文括号!这对括号用于限定需要被print的内容。

在后续的课程中,你会经常遇到类似print()这样的结构,用于描述指令和执行指令时必要的信息,我们会在第二单元正式解释这个结构,现在你只需要了解即可。

在小括号中的'hello, world!',与实际显示在输出面板中的内容hello, world!,有一个显著的区别,你注意到了吗?

对!是引号!

这里的引号用于表示这里出现的任何符号仅具有字面意义,并没有代码含义。计算机看到引号后,将不会解析为需执行的命令,而是将其中的内容看作一句普通的文本。

我们将在下节课了解更多关于引号中内容的情况。

请根据你刚刚所学的内容,猜测下面两行代码将输出什么内容?

python
print(2 + 3)
print('2 + 3')

语法错误

#explore-grammar

如果我们没有遵守符号的约定,写出了「错误」的代码,计算机会怎么做呢?

请尝试运行下面的三组代码,看看输出面板上会显示什么内容?

python
# 缺少引号
print(hello, world!)
python
# 错用中文括号
print('hello, world!')
python
# 拼错单词
printer('hello, world!')

这样因为不符合符号约定的错误写法,被称作语法错误。通常在输出面板上可以看到SyntaxError的提醒,表示我们写错啦!

在写代码时,出现错误非常非常正常。计算机中的每个符号都是被重新赋予了特定的含义,长得相似的代码,其实际作用可能却天差地别。请在日后与代码相处的时光里,耐下性子来仔细编写吧!

本节练习:标签与计算结果

#practice

在 在线 IDE 里写一份最短的实验标签。第一行用 print 输出带引号的字面文字 1.2 + 0.8;第二行输出同一算式去掉引号后的结果,应为 2.0。两行应当不同:一行是给人读的字,一行是机器做完的加法。

本节要点

#review
  • 程序把「先做什么、再做什么、何时停止」写成可执行步骤。单有机器或单有纸上的说明都不够;二者合在一起,才出现现代意义上的计算。
  • 编程语言是人与机器之间的翻译层。不同语言隐藏不同细节。本课用 Python,是因为它适合理解计算思想,又接近真实的科学工作;它不是唯一正确的语言。
  • print(...) 把选定的内容交给人看。括号限定要输出的内容,须用英文括号。
  • 引号把其中的符号声明为字面内容,机器不再当作待执行的运算。因此 print(2 + 3) 与 print('2 + 3') 结果不同。
  • 不符合符号约定的写法会引发语法错误(如 SyntaxError)。报错是定位问题的证据,写错代码很常见。

单选题

程序是什么

下面哪一项最接近「程序」在本课中的含义?

单选题

引号的作用

下面两行分别输出什么? print(2 + 3) print('2 + 3')

单选题

语法错误

下面哪一种写法最可能导致语法错误?

单选题

print 做什么

本课中 print 的主要作用更接近哪一项?

未登录时不会保存学习进度