计算、机器与语言
Introduction to Computation
这门课的第一讲不教语法。先弄清楚三件事:计算机凭什么能算、程序是怎么跑起来的、以及为什么我们用 Python 而不是别的语言。
本讲结束后你应当能
- 说清楚冯诺依曼体系的五个部件各自负责什么
- 理解「一切都是 0 和 1」这句话具体指什么
- 分辨编译器和解释器的区别,说出 Python 属于哪一类
- 写出并运行你的第一个 Python 程序
- 知道这门课的 AI 使用政策,以及为什么前七周要禁
本页目录
这门课要把你带到哪里
十六周之后,你应该能做到这些事:
拿到一个用中文描述的问题——比如”统计这份名单里每个姓出现了多少次”——把它拆成几个步骤,用 Python 写出来,跑通,并且在它出错的时候知道该看哪一行。
看到一段别人写的代码,能读懂它在干什么,能判断它写得好不好,能发现它在什么输入下会崩。
以及,能和 AI 一起写代码——不是让它替你写,而是你知道该让它做什么、不该让它做什么,以及怎么验证它给你的东西。
这门课不要求任何基础。如果你高中学过一点编程,很好;如果你连”程序”是什么都没概念,也完全没问题——这门课就是为你设计的。
计算这件事
人算了几千年
在有计算机之前,“计算”是人干的活。中国的算盘、欧洲的计算尺、天文台里成千上万页的对数表——都是为了让人算得快一点、错得少一点。
天文学家和航海家需要大量的三角函数表和对数表,这些表由一批被称为 computer 的人手工算出来。computer 这个词最早指的是”计算的人”,而不是机器。
问题是人会累,会走神,会算错。而且一旦某一页表算错了,所有依赖它的航海图都跟着错。
十九世纪,英国人查尔斯·巴贝奇(Charles Babbage)想造一台机器来干这件事。他设计了差分机和分析机——分析机已经有了我们今天所说的处理器、存储器和输入输出的雏形,可以用打孔卡编程。这台机器最终没有造出来(当时的机械加工精度不够),但设计图留下来了,所以巴贝奇常被称为”计算机之父”。
和巴贝奇合作的阿达·洛芙莱斯(Ada Lovelace, 1815–1852)为分析机写下了一组指令,用来计算伯努利数。这被认为是世界上第一个计算机程序——写在一台从未存在过的机器上,比第一台真正的计算机早了一百年。
她还看到了一件巴贝奇没看到的事:这台机器不只能算数,只要能把别的东西(比如音符)编码成数字,它就能处理任何东西。这个洞见是今天一切数字技术的起点。
三次跃迁
机器真正开始计算,用了三种截然不同的物理手段:
| 时期 | 靠什么开关 | 代表 | 规模 |
|---|---|---|---|
| 1930s–40s | 继电器(机械触点) | Zuse Z3 | 一个房间 |
| 1940s–50s | 电子管(真空管) | ENIAC | 一个大厅,18000 支管子 |
| 1947 至今 | 晶体管 → 集成电路 | 从 MOS 6502 到今天的手机芯片 | 一枚指甲盖 |
三次跃迁做的其实是同一件事:把”开关”做得更小、更快、更省电。
1947 年贝尔实验室发明晶体管,是这条线上最关键的一步。1970 年的 MOS 6502 处理器上有 3500 个晶体管;今天一枚手机芯片上有几百亿个。制程从 10 微米走到 3 纳米——3 纳米大约是十几个硅原子排成一列的宽度。
摩尔定律说了什么
1965 年,英特尔的创始人之一戈登·摩尔观察到一个规律:集成电路上能容纳的晶体管数目,大约每 18 个月翻一番。
这句话有三种等价的读法,三种都重要:
- 性能:同样的价格,18 个月后能买到快一倍的机器
- 价格:同样的性能,18 个月后价格减半
- 尺寸:同样的功能,18 个月后体积缩小一半
它不是物理定律,是一个经验观察,而且近年来已经明显放缓。但它塑造了过去半个世纪的整个行业——你今天手里的手机,算力超过 1990 年代的超级计算机。
这对你意味着什么:很多在二十年前”算不动”的问题,今天可以硬算。计算已经成为科学理论落到现实的必经之路——对于复杂到无法用纸笔推理的问题,建立数学模型、设计算法、让机器去算,往往是唯一可行的路。
一个标志性的瞬间
1997 年,IBM 的深蓝在国际象棋上击败世界冠军卡斯帕罗夫。2016 年,AlphaGo 在围棋上击败李世石。
这两件事之间隔了 19 年,因为围棋的搜索空间远大于国际象棋,靠深蓝那种”把所有可能都算一遍”的路子走不通。AlphaGo 换了一条路——不再穷举,而是学习。
你正好在这条线的下一个阶段入学:现在的模型不只会下棋,还会写代码。这件事对这门课意味着什么,我们在最后一节讨论。
计算机是怎么搭起来的
冯诺依曼体系
1945 年,约翰·冯·诺依曼在一份报告里描述了一种计算机结构。今天你能接触到的几乎所有计算机——手机、笔记本、服务器、路由器——都是这个结构的变体。
它由五个部件组成:
| 部件 | 干什么 | 你电脑上对应什么 |
|---|---|---|
| 运算器 | 做加减乘除和逻辑判断 | CPU 的一部分 |
| 控制器 | 决定下一条指令是什么 | CPU 的另一部分 |
| 存储器 | 存放数据和程序 | 内存、硬盘 |
| 输入设备 | 把外界信息送进来 | 键盘、鼠标、摄像头 |
| 输出设备 | 把结果送出去 | 屏幕、音箱、打印机 |
这个设计里最关键、也最容易被忽略的一点是:程序和数据存在同一个地方,用同样的方式表示。
这叫”存储程序”思想。它的后果是:机器不需要重新接线就能换任务,只要把另一段程序读进存储器就行。而且——程序本身也可以被当作数据来处理。编译器、解释器、以及你在这门课后期会遇到的很多技巧,根基都在这里。
一切都是 0 和 1
存储器里存的是什么?只有两种状态:高电压和低电压,我们记作 1 和 0。
一个 0 或 1 叫一个 bit(比特,位)。八个 bit 叫一个 byte(字节)。
那么问题来了:一串 0 和 1 到底是什么意思?
答案是——取决于你怎么解释它。同样一串 01000001:
- 当作整数看,是 65
- 当作 ASCII 字符看,是字母
A - 当作机器指令看,可能是某条 CPU 指令
- 当作图片的一个像素看,可能是某个灰度值
二进制序列本身没有意义,意义来自约定。 这是理解计算机的一把钥匙,L2 会详细展开。
先感受一下十进制和二进制的对应关系:
n = 2026
print("十进制:", n)
print("二进制:", bin(n))
print("八进制:", oct(n))
print("十六进制:", hex(n))
# 反过来,把二进制串还原成整数
print(int("11111101010", 2))
软件与操作系统
硬件是一堆能通电的元件。让它们做有用的事,需要软件——一组指令、数据和程序。
其中最重要的一个软件叫操作系统(OS)。它管理硬件资源,并向其他程序提供统一的服务:
- 你写
open("data.txt")的时候,不需要知道硬盘的磁头在哪个磁道 - 你同时开着浏览器和音乐播放器,是操作系统在决定 CPU 现在给谁用
- 你按下键盘,是操作系统把这个事件送到当前的窗口
Windows、macOS、Linux、iOS、Android——都是操作系统。这门课的实验环节会带你接触 Linux 命令行(Lab 8),因为几乎所有的服务器、科学计算集群都跑在 Linux 上。
三个思想的来源
计算机能存在,靠的不只是工程。二十世纪三四十年代,三个人分别回答了三个根本问题。
图灵:什么叫”可以计算”
阿兰·图灵(Alan Turing, 1912–1954)在 1936 年提出了一个极简的假想机器:一条无限长的纸带,一个读写头,一张状态转移表。它每次只能读一格、写一格、左移或右移一格。
这台”图灵机”简单到不可思议,但图灵证明了:任何能被机械地计算出来的东西,都能用它算出来。
这给了”计算”这个含糊的词一个精确的定义。也顺带划出了边界——有些问题任何计算机都解不了,不是算得慢,是根本不存在算法。最著名的是停机问题:不存在一个程序,能判断任意给定的程序是否会陷入死循环。
图灵在二战中破译德军的 Enigma 密码,对战争进程有实质影响。计算机科学的最高奖项以他命名。
香农:信息可以被度量
克劳德·香农(Claude Shannon, 1916–2001)做了两件事。
1937 年,他在硕士论文里指出:布尔代数(真/假、与/或/非)可以用继电器电路实现。这篇论文让”用电路做逻辑运算”成为可能,是所有数字电路的理论起点。
1948 年,他发表《通信的数学理论》,提出用 bit 度量信息量,并证明了信道容量的极限。今天的手机通信、文件压缩、纠错编码,都建立在这套理论上。
哥德尔:形式系统有边界
库尔特·哥德尔(Kurt Gödel, 1906–1978)在 1931 年证明了不完备定理:任何足够强的、逻辑自洽的形式系统,都存在在系统内既无法证明也无法证伪的命题。
这粉碎了当时数学界”把全部数学建立在一套完备公理上”的雄心。图灵的停机问题、以及计算机科学中一系列”不可判定”的结论,本质上和它是同一件事的不同面孔。
这三个人给出的是同一个故事的三个侧面:什么能算(图灵)、算什么(香农)、以及什么算不了(哥德尔)。
语言:人和机器之间
同一句 Hello World
计算机只认 0 和 1。所谓编程语言,是人和机器之间的翻译层。
同一件事——在屏幕上打印 Hello world——用三个层次的语言写出来:
机器语言,CPU 直接执行的东西:
01001000 01100101 01101100 01101100 01101111
汇编语言,给机器指令起了助记名字:
section .text
global _start
_start:
mov edx, len
mov ecx, msg
mov ebx, 1
mov eax, 4
int 0x80
Python:
print("Hello world")
三者做的是同一件事。差别在于,写第一种你需要记住 CPU 的指令编码,写第三种你只需要说出你想要什么。
编程语言的演化方向很清楚:离机器越来越远,离人越来越近。 代价是运行效率——越高级的语言通常越慢,因为中间隔的翻译层越多。这是一笔交易:用机器的时间换人的时间。而按摩尔定律,机器的时间越来越便宜,人的时间越来越贵。
为什么这门课用 Python
编程语言有几百种,选哪一种教零基础的学生,是有讲究的。
学一门语言要学两样东西:语法(syntax,怎么写才合法)和语义(semantics,写出来是什么意思)。对初学者来说,语法的负担应该尽量小,注意力才能放在语义和问题本身上。
对比一下同样打印一行字:
// C
#include <stdio.h>
int main() {
printf("Hello world\n");
return 0;
}
// Java
public class Hello {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
# Python
print("Hello world")
C 和 Java 的版本里,#include、int main、public static void 这些东西,对一个刚开始学的人全都是需要解释的负担。而它们和”打印一行字”这件事本身毫无关系。
Python 的取舍是:
- 对初学者友好——语法简明,细节少,学习曲线平缓
- 实用——科学计算、数据分析、机器学习、Web、自动化脚本都能用,你在后续课程和科研里大概率还会用到它
- 开放——开源,不受任何商业公司控制,社区庞大
代价是慢。纯 Python 代码比 C 慢一到两个数量级。但绝大多数场合这不重要,而重要的场合有 NumPy 这样的库(底层是 C 写的)来兜底。
Python 的来历
Python 由荷兰人吉多·范罗苏姆(Guido van Rossum)在 1989 年圣诞节前后开始编写。名字来自英国喜剧团体 Monty Python,和蟒蛇没关系。
有一个坎值得知道:Python 3.0(2008 年)是不向后兼容的。也就是说 Python 2 写的代码,Python 3 不一定能跑。这次断裂造成了长达十年的生态分裂,直到 2020 年 Python 2 正式停止支持才结束。
这门课用 Python 3.13。 你在网上搜到的老代码如果写着 print "hello"(没有括号),那是 Python 2 的写法,已经不能用了。
代码是怎么跑起来的
你写的 .py 文件是一个文本文件,CPU 看不懂。中间必须有个东西把它翻译成机器能执行的形式。有两种做法。
编译器(compiler):在运行之前,把整个源程序一次性翻译成机器码,生成一个可执行文件。之后每次运行都直接跑这个文件。C、C++、Rust 走这条路。
- 优点:运行快,因为翻译的成本只付一次
- 缺点:改一行代码就要重新编译;编译出来的文件只能在特定平台上跑
解释器(interpreter):不预先翻译,而是在运行时逐条读取、逐条执行。Python、JavaScript 走这条路。
- 优点:改完立刻能跑,跨平台,可以交互式地一句一句试
- 缺点:慢,因为翻译的成本每次运行都要付
Python 是解释型语言。 你装的那个 python 命令就是解释器——准确地说,是用 C 语言实现的解释器,叫 CPython(还有别的实现,比如 PyPy、Jython,这门课不涉及)。
实际情况稍微复杂一点:CPython 会先把源码编译成一种中间形式(字节码,bytecode),再由虚拟机执行字节码。你会在项目目录里看到 __pycache__ 文件夹,里面的 .pyc 就是缓存下来的字节码。这个机制我们在 L10 再讲。
import sys
print("Python 版本:", sys.version.split()[0])
print("运行平台:", sys.platform)
IDE 是什么
IDE(Integrated Development Environment,集成开发环境)是把写代码要用的工具打包在一起的软件:编辑器、运行按钮、调试器、错误提示、代码补全。
这门课推荐 Visual Studio Code(VS Code)。它免费、跨平台、插件生态好。PyCharm 也很不错,专业版对学生免费(用 edu 邮箱申请)。
Python 自带的 IDLE 和命令行只适合临时试几句,不要用它写作业。
安装和配置的完整步骤在 Lab 1,第一次实验课会带着做。
为什么 Python 是免费的
你下载 Python 不用付钱,也不用注册。这不是理所当然的。
1960 年代,计算机公司靠卖硬件赚钱,软件是附带白送的。后来硬件越来越便宜,利润越来越薄,厂商开始把软件单独收费、并且不再提供源代码。
作为反弹,出现了自由软件与开源运动,主张软件的源代码应当公开、可以被自由使用和修改。它靠许可证(license)来实现——许可证是一份法律文件,规定了别人可以拿你的代码做什么。常见的有 MIT、Apache、BSD、GPL 等,它们在”改了之后必须不必开源”这类问题上有不同规定。
1991 年,芬兰学生林纳斯·托瓦兹(Linus Torvalds)在一个邮件列表里发了一条消息,说自己在做一个免费的操作系统,“只是个业余爱好,不会像 GNU 那样又大又专业”。那个东西就是 Linux。今天全世界绝大多数服务器、以及所有 Android 手机,跑的都是 Linux 内核。
Python 本身、你会用到的 NumPy、Matplotlib、以及几乎所有科学计算工具,全都是开源的。你站在几十年、成千上万人的无偿工作之上。 这值得知道。
你的第一个程序
print("Hello world")
点一下运行。
print 是一个函数,作用是把括号里的东西显示出来。引号里的内容叫字符串,原样输出。
多试几句:
print("Shanghai Jiao Tong University")
print("上海交通大学")
print(2026)
print(1 + 2 + 3 + 4 + 5)
注意最后两行:print(2026) 里的 2026 没有引号,是一个数;print(1 + 2 + 3 + 4 + 5) 会先算出 15 再打印。引号里的东西原样输出,引号外的东西先求值再输出。
Python 之禅
在解释器里输入 import this,会打印一段东西:
import this
这是 Python 社区的价值观,由 Tim Peters 写成。其中几条你现在就能用上:
- Beautiful is better than ugly. — 好看比难看好
- Explicit is better than implicit. — 明确比隐晦好
- Simple is better than complex. — 简单比复杂好
- Readability counts. — 可读性很重要
- There should be one obvious way to do it. — 做一件事应该有一种显而易见的方法
这些话现在看是空的。学到 L13 你再回头看,会有完全不同的感受。
这门课怎么上
结构
十六讲编入六个部分,每部分收口在一个具体的能力上:
| Part | 主题 | 学完能做什么 |
|---|---|---|
| I | 计算基础与 Python 入门 | 写出含输入、判断、循环、函数的完整程序 |
| II | 数据的组织 | 为问题选对容器,处理批量数据 |
| III | 问题求解与 AI 协作 | 拆解问题;读懂、审查、验证别人(含 AI)写的代码 |
| IV | 抽象与组织 | 用类和模块组织中等规模程序 |
| V | 健壮性与真实世界 | 评估效率、处理异常、读写真实数据 |
| VI | Pythonic 与现代实践 | 写出地道的 Python;用 AI 完成一个真实项目 |
理论课 32 学时,实验课 32 学时。实验课才是你学会的地方——理论课能让你听懂,但只有自己写、自己出错、自己找出来,才会变成你的能力。
成绩
| 项目 | 占比 |
|---|---|
| 平时作业 | 10% |
| 个人项目 A / B | 15% |
| 团队项目 | 25% |
| 期末考试(闭卷) | 50% |
AI 使用政策
这是这门课最重要的一条规则,请认真读。
第 1–7 周:不允许用 AI 生成或补全代码。 请关闭编辑器里的 AI 补全功能。你可以用 AI 问概念、查文档、解释报错信息,但不能让它替你写代码。
第 8 周起:允许使用,但每次提交要附一段声明,说明你用了什么工具、它生成了哪部分、你如何验证它是对的。
第 15–16 周(团队项目):完全开放。
为什么前七周要禁——这一点必须说清楚,否则这条规则会被当成形式主义:
前七周你要建立的东西是代码直觉和调试能力。看到一段代码能预判它会输出什么;看到一个报错能猜到问题在哪一行。这两样东西没有捷径,只能靠自己写、自己错、自己找出来。
如果这个阶段交给 AI,你会得到一堆能跑的代码,但得不到判断代码对错的能力。而从第八周起,判断力恰恰是你使用 AI 时最值钱的东西——AI 经常写出看起来完全合理、但在边界情况下崩溃的代码。没有前七周的积累,你根本看不出来。
换句话说:前七周的限制,是为了让你在后面能真正用好 AI,而不是被它牵着走。
完整规则在 AI 使用政策。
遇到问题怎么办
按这个顺序:
- 读报错信息。 它通常直接告诉你哪一行、什么问题。新生最常见的毛病是看到红字就慌,根本没读。
- 查官方文档。 docs.python.org 有完整中文版。
- 搜索。 把报错信息里的关键部分贴到搜索引擎里,大概率有人遇到过同样的问题。
- 问同学、问助教。 课程群里有问必答。
- 问 AI——在政策允许的范围内。
动手
- 在你自己的电脑上装好 Python 和 VS Code,跑通
print("Hello world")。完整步骤见 Lab 1。 - 用
print()输出你的姓名、学号和一句你想说的话。 - 用
bin()、oct()、hex()看看你的学号在二进制、八进制、十六进制下长什么样。 - 运行
import this,挑一条你现在最认同的,想想它可能是什么意思。学期末再回来看看想法有没有变。 - 故意写错一行代码——比如用中文括号,或者把
print拼成pirnt——看看报错长什么样。从第一天起就习惯读报错。