《Python编程入门》1.1 Python 的诞生与设计哲学

本节从 1989 年圣诞假期 Guido van Rossum 起意写一个「业余项目」讲起,梳理 Python 从 ABC 语言继承与拒绝了什么,以及 1991 年 0.9.0 首次发布的经过。随后逐条解读 import this 打印的「Python 之禅」,说明「可读性优先」「显式优于隐式」如何被翻译成今天的语言行为。读完本节,你能用设计哲学解释 Python 的许多反直觉之处。

本节目标:搞清楚 Python 从哪里来、它的设计哲学究竟规定了什么,并能用这套哲学解释语言里的许多「怪」行为。
适用版本:Python 3.12+(实测 3.14.6)

1.1 Python 的诞生与设计哲学

多数教程从 print("Hello, World") 开始,这没错,但你会把 Python 当成一堆语法的拼盘。要真正用好它,得先知道它为什么长成今天这样——因为 Python 的很多「反直觉」行为,其实是几十年前一以贯之的设计选择。

1.1.1 1989 年的圣诞假期

1989 年 12 月,荷兰 CWI(国家数学与计算机科学研究中心)的 Guido van Rossum 在圣诞假期里,想给自己找一个能「打发时间」的编程项目。他刚参与过一个叫 ABC 的教学语言项目,对它的结局心有不甘,于是决定动手写一个脚本语言。

这个「业余项目」就是 Python。名字来自他喜欢的英国喜剧团体 Monty Python,跟蟒蛇没关系——这也是为什么官方文档里常出现「spam」「eggs」这类梗。

时间线大致是:

时间事件
1989-12Guido 在圣诞假期开始动手
1991-02Python 0.9.0 发布到 alt.sources 新闻组
1994-01Python 1.0 发布
2000-10Python 2.0 发布
2008-12Python 3.0 发布

0.9.0 这个版本号值得注意:它发布时就已经带着类、异常、函数、核心数据类型,以及用 import 组织模块的能力。换句话说,Python 不是从「能算个加法」慢慢长起来的,它一开始就瞄准了「能写真正的程序」。

1.1.2 从 ABC 继承了什么,又拒绝了什么

理解 Python 最快的办法,是看它从 ABC 那里学到了什么教训。ABC 是一门面向初学者的语言,语法漂亮、错误提示友好,但它失败了——问题不在语法,而在「封闭」。

ABC 的做法结果Python 的选择
用缩进表示代码块可读性好,但没人接受保留缩进作为语法
内置一套高级数据类型好用,但无法扩展内置常用类型,同时开放扩展
「一切都已内置」无法接入操作系统、无法写系统工具提供 C 接口,允许写扩展模块
设计上追求纯净学术上优雅,工程上难用实用主义优先

最后一行是 Python 最重要的基因。Guido 后来总结说,Python 的目标是「让程序员更高效」,而不是「让语言理论更漂亮」。当「优雅」和「有用」冲突时,Python 通常选有用——这一点你会在整本书里反复遇到。

1.1.3 import this:Python 之禅

Python 藏着一个彩蛋。在终端里执行:

python3 -c "import this"

它不会报错,而是打印出 Tim Peters 写下的一段话(记录在 PEP 20 )。下面是我在 Python 3.14.6 上运行的真实输出:

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

import this 看起来什么都没做,其实 this 模块在被导入时会执行一段打印代码——这是 Python「模块导入即执行」机制的一个无害示例。第 5 章会专门讲这套机制。

1.1.4 逐条解读:哪些真正在塑造语言行为

19 句话里,真正能对应到具体语言行为的其实是一部分。下面挑出最关键的几条,看它们如何落地。

禅语翻译成今天的什么行为
Beautiful is better than ugly强制缩进、一致的标准库命名(snake_case)
Explicit is better than implicit没有隐式类型转换、import 不自动展开、if x is None
Simple is better than complex一个 for 循环能遍历任何可迭代对象
Readability counts缩进是语法,代码排版不可随意
Errors should never pass silently异常不会被静默吞掉,除非你显式 except
Refuse the temptation to guessint("abc") 直接报错,而不是给个默认值
One obvious way to do it字符串格式化最终收敛到 f-string
Namespaces are one great idea模块、包、__name__ 的核心地位

反过来说,「Although practicality beats purity」是那句让 Python 不走向教条的话——它承认现实:有些地方就是会有不止一种写法。

1.1.5 「可读性优先」如何变成语法

Python 用缩进划分代码块,这不是风格建议,而是语法要求。下面这段代码直接报错:

if True:
print("缩进错了")

真实的报错是:

IndentationError: expected an indented block after 'if' statement on line 1

把「可读性」做成语法,代价是你不能再靠大括号「蒙混过关」,收益是任何人的 Python 代码看起来都差不多。这也是 Python 在团队协作中口碑好的重要原因。

1.1.6 「显式优于隐式」的几个真实例子

这条哲学最难被初学者接受,因为「隐式」往往写起来更短。但在 Python 里,短不是目标,清楚才是。

# 1 + True 是 2:bool 是 int 的子类,这是历史包袱,Python 并不为此辩护
print("1 + True =", 1 + True)

# 但真正的「隐式转换」——字符串自动变数字——Python 坚决不做
try:
    print("1" + 1)
except TypeError as e:
    print("TypeError:", e)
1 + True = 2
TypeError: can only concatenate str (not "int") to str

同一个 +,JavaScript 会悄悄拼成字符串,Python 直接报错。它宁可让你多写一行显式转换,也不让你在半夜 debug 一个类型错误。

再看 str 与 repr 的分工,这是「显式」的另一个体现:

print(repr("a\nb"))   # repr:给开发者看,转义可见
print(str(["a", "b"]))  # str:给人看,尽量可读
'a\nb'
['a', 'b']

1.1.7 「应该有一种——最好只有一种——明显的方式」

这句话常被误读成「Python 只有一种写法」。它的原话是 “There should be one– and preferably only one –obvious way to do it”,紧接着还有一句自嘲:「除非你是荷兰人」(Guido 是荷兰人)。

它的真实含义是:语言的设计者应该主动收敛方案,而不是把选择都甩给用户。几个例子:

  • 遍历序列,用 for x in seq,不要手写索引循环。
  • 打开文件,用 with open(...),不要手动 close。
  • 格式化字符串,今天首选 f-string,而不是 % 或 str.format。

但这条是理想,不是事实。列表拼接既有 + 也有 list.extend,还有推导式;同一个任务经常有好几种写法。Python 的态度是「尽量收敛,但不强求」——它不会为了统一而删掉一个大家都在用的写法(第 1.2 节你会看到,真正被强删的 print 语句,引发了多大的动荡)。

1.1.8 TOOWTDI 从何而来:与 Perl 的对照

「只有一种明显的方式」这句禅语,其实是对另一门语言哲学的有意回应。1987 年诞生的 Perl 有一句著名口号:TIMTOWTDI——“There’s More Than One Way To Do It”(做一件事的方式不止一种)。Perl 把「自由」当美德,同一件事能写出十种风格。

Python 选了相反的立场。Guido 说过,TOOWTDI 是对 TIMTOWTDI 的反叛:

维度Perl(TIMTOWTDI)Python(TOOWTDI)
核心价值表达自由、写法多样可读性、团队一致
对「聪明」代码的态度鼓励警惕
标准库设计功能多、风格杂每个任务一个推荐方案
读别人代码的成本高低

这不是谁对谁错,而是取舍:Perl 适合写一次性的文本处理脚本,Python 适合多人长期维护的项目。理解了这一点,你就明白为什么 Python 社区对「炫技式的一行代码」普遍不感冒。

1.1.9 哲学落到标准库上:pathlib 的例子

TOOWTDI 不只是口号,它驱动着标准库的演化。文件路径处理就是最好的例子。

早期 Python 用 os.path 处理路径,它是纯函数式的,把路径当字符串拼接:

import os
p = os.path.join("data", "raw", "file.csv")
print(os.path.splitext(os.path.basename(p)))
('file', '.csv')

能用,但 os.path.join、os.path.basename、os.path.splitext 套在一起读起来费劲。3.4 引入了 pathlib,把路径变成对象:

from pathlib import Path
p = Path("data") / "raw" / "file.csv"
print(p.name, p.stem, p.suffix)
file.csv file .csv

/ 运算符被重载成路径拼接,.stem、.suffix 直接是属性。这就是「一种明显的方式」的典型落地:同一件事(处理路径)从「一堆函数」收敛到「一个对象加几个属性」。今天写新代码,pathlib 是推荐方案,os.path 主要留给兼容老代码。后续 10.2 文件 I/O、pathlib 与编码 会系统展开 pathlib 的用法。

1.1.10 三个常见误解

误解事实
「Python 很慢,因为它是解释型语言」它先编译成字节码再执行,「解释型」这个标签并不准确(见 1.3 解释器实现与执行模型 )
「Python 之禅是强制规范」它是设计倾向的总结,违反它不会报错,只是不 Pythonic
「显式优于隐式 = 什么都要写出来」它反对的是语言替你做决定,不是反对抽象

第一条尤其常见。等你在 1.3 节亲手用 dis 拆开字节码,就会明白「解释型 vs 编译型」这个二分法本身就有问题。

1.1.11 学完本节你应该能回答的问题

  • Python 诞生于哪一年、在什么背景下、由谁主导?(1.1.1)
  • 它从 ABC 继承了缩进,却拒绝了什么?为什么这很关键?(1.1.2)
  • import this 输出里,哪几句话最能解释「Python 不做隐式类型转换」?(1.1.4、1.1.6)
  • 「应该只有一种明显的方式」是事实还是理想?(1.1.7)
  • TOOWTDI 是在回应哪门语言的哪句口号?(1.1.8)

把这些问题串起来,你就拥有了一套稳定的心智模型:Python 的设计目标始终是「让人写得清楚、看得明白」,而不是「让语言理论更漂亮」。 后面遇到任何觉得别扭的语法,先问「它想让我更明确地表达什么」,通常都能想通。

小结

  • Python 诞生于 1989 年圣诞假期 Guido van Rossum 的业余项目,1991 年 2 月以 0.9.0 首次发布。
  • 它从 ABC 继承缩进与高级数据类型,但拒绝封闭,选择了可扩展与实用主义。
  • import this 打印的「Python 之禅」是 19 条设计倾向,其中「可读性优先」「显式优于隐式」「只有一种明显方式」最能解释语言行为。
  • 「显式优于隐式」意味着 Python 宁可报错,也不做隐式类型转换;「只有一种明显方式」是理想而非事实。
  • 下一节我们会看 Python 历史上最痛的一次断代——2 到 3 的迁移。

本节建立的「设计哲学 → 语言行为」视角,会直接用在下一节:当你想不通「为什么 Python 2 到 3 要付出这么大代价也要改」,答案就藏在「显式优于隐式」里。

阅读导航:上一节:目录 · 下一节:1.2 Python 2 到 3、发布节奏与版本选择 。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「python」更多文章

  1. 《Python高级编程》目录
  2. 《Python高级编程》11.3 PEP 流程与版本迁移策略
  3. 《Python高级编程》11.2 嵌入式与自由线程运行时