大家好,我是正在实战各种 AI 项目的程序员晚枫。
用 C 编写 Python 模块,突破性能瓶颈!NumPy、Pandas 为什么这么快?答案就在这一讲。
📖 开篇:为什么需要 C 扩展?
Python 很快,但不是所有场景都快:
1 | # Python 循环:慢 |
NumPy、Pandas、TensorFlow 都是 C/C++ 扩展的典型例子。
🔧 开发环境准备
1 | # 安装编译工具 |
📝 最简单的 C 扩展
1 | // mymodule.c |
编译安装
1 | # setup.py |
1 | # 编译并安装 |
使用
1 | import mymodule |
📊 参数解析
PyArg_ParseTuple 是 C 扩展中最重要的函数:
1 | static PyObject* math_ops(PyObject* self, PyObject* args) { |
常用格式字符串
| 格式 | Python 类型 | C 类型 |
|---|---|---|
i | int | int |
l | int | long |
d | float | double |
s | str | char* |
O | 任意 | PyObject* |
ii | int, int | int, int |
(i,i) | tuple | int*, int* |
🧠 处理 Python 对象
操作 Python 列表
1 | static PyObject* sum_list(PyObject* self, PyObject* args) { |
引用计数(最重要!)
1 | // 规则 1:PyArg_ParseTuple 不增加引用计数,无需 DECREF |
引用计数错误是 C 扩展中最常见的 bug:
- 忘记 DECREF → 内存泄漏
- 多次 DECREF → 崩溃
⚡ 高性能示例:向量化加法
1 | // fastmath.c |
对比性能:
1 | # Python 版本 |
🔄 Cython(更简单的方式)
如果不想直接写 C 代码,可以用 Cython:
1 | # fastcython.pyx |
1 | # setup.py |
💡 本节作业
- 用 C 扩展实现一个
factorial(n)函数 - 用
PyArg_ParseTuple解析多个参数 - 尝试用 Cython 改写一个 Python 函数
🎯 本讲总结
C 扩展基础:PyObject*、PyArg_ParseTuple、方法表、模块初始化函数。
参数解析:格式字符串(i、s、O 等)解析 Python 参数为 C 类型。
引用计数:借用引用 vs 新引用,DECREF 错误是最常见的 bug。
性能对比:C 扩展比纯 Python 快 10-100 倍,Cython 是更简单的替代方案。
📚 推荐教材
《Python 编程从入门到实践(第 3 版)》 | 《流畅的 Python(第 2 版)》 | 《CPython 设计与实现》
🔗 课程导航
← 上一讲:模块导入系统 | 下一讲:性能分析与优化 →
💬 联系我
| 平台 | 账号/链接 |
|---|---|
| 微信 | 扫码加好友 |
| B 站 | Python 自动化办公社区 |
主营业务:AI 编程培训、企业内训、技术咨询