Python:一门"算得慢"的语言,为什么统治了半个世界

先说个反直觉的事实

2026 年,全球跑深度学习训练的语言里,Python 写的代码几乎不参与真正的运算。CUDA 核函数是 C++ 写的,矩阵乘法是 cuBLAS 里手写的汇编和 PTX,PyTorch 的算子调度在 C++ 里,Python 只负责把计算图"搭"出来。用 time.perf_counter() 测一个纯 Python 的 for 循环,一百万次加法大约 30~50 毫秒;同样的事在 C 里是不到 1 毫秒。差了三十倍以上。

那为什么还是它?

因为现代软件工程的瓶颈早就不是"CPU 每秒执行多少条指令",而是"一个人一周能产出多少可维护的代码"。Python 用极低的语法摩擦换来了极高的迭代速度,再把真正的重活外包给 C/C++/Rust 写的底层库。这不是偷懒,这是一次成功的分工。

它是怎么长成今天这样的

Guido van Rossum 1989 年圣诞假期开始写这个项目,1991 年发布第一版。名字取自他喜欢的喜剧团体 Monty Python,不是蟒蛇。最初定位很朴素:一门能教编程、能写系统脚本、比 C 好用的语言。

真正让它起飞的是三个时间点:

  • 2000 年 Python 2.0:引入列表推导、垃圾回收、Unicode 支持,开始有"现代语言"的样子。
  • 2008 年 Python 3.0:print 从语句变成函数,字符串默认 Unicode。这次不兼容升级让社区痛苦了整整十二年,直到 2020 年 1 月 1 日 Python 2 正式停止维护才算完。
  • 2015 年之后:NumPy/SciPy 成熟、TensorFlow 与 PyTorch 相继出现,Python 从"运维脚本语言"变成了"科学计算入口"。

一个有意思的细节:Python 3.11(2022)做了一次纯性能专项,官方基准里 CPython 解释器整体快了 10%~60%,其中 pyperformance 几何平均提升约 25%。3.12、3.13 继续沿着这条线优化,3.13 还实验性地解掉了 GIL(PEP 703,自由线程构建)。一门三十多年的语言还在为跑得快做结构性改造,这本身就说明它的位置有多重要。

它的设计哲学,以及这套哲学的代价

import this 会打印出 The Zen of Python,十九条。其中最能解释 Python 行为方式的是这几条:

优美胜于丑陋,明了胜于晦涩。 应该有一种——最好只有一种——显而易见的方式去做一件事。

这带来的是可读性极高的代码。同一段逻辑,Python 的字符量通常只有 Java 的一半、C++ 的三分之一:

# 统计一段文本里出现频率最高的五个词
from collections import Counter
import re

text = open("article.txt", encoding="utf-8").read()
words = re.findall(r"[\u4e00-\u9fa5]{2,}|[A-Za-z]{2,}", text.lower())
top5 = Counter(words).most_common(5)
for w, c in top5:
    print(f"{w:<10} {c:>6}")

代价也很清楚:

一、GIL。 经典 CPython 里,同一进程内多个线程无法并行执行 Python 字节码。所以 CPU 密集任务必须用 multiprocessing 或 concurrent.futures.ProcessPoolExecutor 绕开:

from concurrent.futures import ProcessPoolExecutor
import math

def heavy(n):
    return sum(math.sqrt(i) for i in range(n))

if __name__ == "__main__":          # Windows 下必须放在 __main__ 保护内
    with ProcessPoolExecutor(max_workers=8) as ex:
        print(list(ex.map(heavy, [10**7] * 8)))

3.13 的 free-threaded 构建(python3.13t)能让线程真并行,但单线程会慢 5%~10%,且大量 C 扩展还没适配。目前它仍是"可以试"的状态,不是"该上生产"的状态。

二、动态类型的代价。 类型错了只有运行到那一行才报错。所以类型注解(PEP 484)从 2015 年被引入后逐步成为工程标配:

from dataclasses import dataclass

@dataclass(frozen=True, slots=True)
class Order:
    id: int
    amount: float
    currency: str = "CNY"

def total(orders: list[Order], rate: float = 1.0) -> float:
    return sum(o.amount for o in orders) * rate

注意注解在运行时完全不检查,它只是给 mypy / pyright / pyre 这类静态检查器和 IDE 看的。生产项目里通常把 mypy --strict 挂进 CI,这才是注解真正兑换价值的地方。

三、打包与依赖。 这是 Python 被吐槽最多的地方。pip + venv 的组合在十年前还够用,现在是 uv(Astral 出品,Rust 写的)在快速取代它——装包速度比 pip 快 10~100 倍,还能顺带管 Python 版本和项目锁文件:

uv init myapp && cd myapp
uv add pandas polars
uv run python main.py

如果还在用 pip install -r requirements.txt 加手工 venv,2026 年确实该换了。

生态:这才是护城河

  • 数据与科学计算:NumPy、pandas、Polars(Rust 内核,大表比 pandas 快数倍、内存占用低得多)、DuckDB(进程内 OLAP,直接 SQL 查 DataFrame)。
  • 机器学习:PyTorch 在论文复现里仍是事实标准;scikit-learn 撑着传统机器学习;Hugging Face 的 transformers 让加载模型变成三行代码。
  • Web:FastAPI(基于 Pydantic + Starlette,自动生成 OpenAPI 文档)已经超过 Flask 成为新项目首选;Django 仍是"什么都要有"的全家桶。
  • 自动化与运维:Ansible、SaltStack 本身就是 Python 写的;爬虫有 Scrapy、Playwright 的 Python 绑定。
  • 桌面:PySide6 / PyQt6 够用,但这一块确实不是它的强项。

PyPI 上的包数量早已超过 50 万,任何一个细分需求——读一个冷门二进制格式、连一台冷门仪器——大概率已经有人写过包了。这个"总能找到现成的"体验,是别的语言很难复制的。

真实性能数字(大概的量级,不是营销数字)

场景 典型表现
纯 Python 循环 10^8 次整数累加 5~15 秒
同样逻辑用 NumPy 向量化 0.1~0.5 秒
同样逻辑用 Numba@njit 0.1 秒左右(首次编译额外几百毫秒)
FastAPI 简单 JSON 接口 单核每秒数千请求(uvicorn + 1 worker)
冷启动导入 pandas 300~600 毫秒(这个常被忽视,CLI 工具会明显卡)

结论很清楚:Python 的性能问题几乎都能靠"别用 Python 做内循环"解决。向量化、C 扩展、Cython、Numba、Rust 绑定(PyO3)都是标准手段。

它不适合什么

  • 硬实时系统(GC 停顿、解释器开销不可控)
  • 移动端原生应用(Kivy/BeeWare 生态弱,主流方案不用它)
  • 前端浏览器(Pyodide 能跑,但那是玩具级)
  • 极致低延迟的高频交易核心路径(可以写策略,撮合不行)
  • 内存受限的嵌入式(MicroPython 能跑,但功能有限)

2026 年该怎么用它

给三条实操建议:

  1. 新项目直接用 uv,别再用 pip + requirements.txt 的手工流程。锁文件、虚拟环境、Python 版本三件事一次解决。
  2. 默认写类型注解,CI 跑 mypy 或 pyright。不用到 --strict 那么狠,但函数签名必须标。半年后你会感谢自己。
  3. 优先选 FastAPI + Pydantic v2(Pydantic v2 的校验核心是 Rust 写的,比 v1 快 5~50 倍)。数据层看数据量:几百 MB 以内 pandas,再往上直接 Polars 或 DuckDB,别硬扛。

Python 不是最快的语言,也不是最安全的语言,但它是最"省人"的语言之一。对于绝大多数业务系统来说,省下来的人力就是最大的性能。