Python - 進階擴展:初學者指南
你好,有抱負的Python程序員!今天,我們將踏上一段令人興奮的旅程,進入Python擴展的世界。如果你是編程新手,不用擔心——我將成為你的友好導遊,逐步解釋一切。那麼,讓我們開始吧!
Python擴展是什麼?
在我們開始之前,讓我們先了解Python擴展是什麼。想象Python是一把瑞士軍刀。它已經非常實用,但有時你需要的工具並不在那裡。這就是擴展的用處——它們就像在你的Python瑞士軍刀中添加新工具。
寫擴展的先決條件
現在,我知道你很渴望開始,但我們需要先設置一些東西。這就像在烹飪美食之前準備你的廚房。以下是您需要的東西:
- 在您的電腦上安裝Python
- 一個C編譯器(如Linux上的GCC或Windows上的Visual Studio)
- Python開發標頭和庫
如果這聽起來很複雜,不用擔心。大多數Python安裝都帶有所需的東西,我會指導您完成任何額外的設置。
仔細看看Python擴展
讓我們從一個簡單的例子開始。想象我們要創建一個函數來添加兩個數字,但我們希望它非常快速。我們可以在C中寫這個,然後在Python中使用它。以下可能是它的樣子:
#include <Python.h>
static PyObject* add_numbers(PyObject* self, PyObject* args) {
int a, b;
if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
return NULL;
}
return Py_BuildValue("i", a + b);
}
static PyMethodDef MyMethods[] = {
{"add", add_numbers, METH_VARARGS, "Add two numbers."},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef mymodule = {
PyModuleDef_HEAD_INIT,
"mymodule",
"A simple module that adds numbers",
-1,
MyMethods
};
PyMODINIT_FUNC PyInit_mymodule(void) {
return PyModule_Create(&mymodule);
}
如果這看起來像字母湯,現在不用恐慌。我們會一塊一塊地分解。
標頭文件Python.h
我們代碼的第一行是:
#include <Python.h>
這就像告訴我們的C程序,“嘿,我們將在這裡使用Python!”它包含了我們創建Python擴展所需的所有必要定義和函數。
C函數
接下來,我們有我們的實際C函數:
static PyObject* add_numbers(PyObject* self, PyObject* args) {
int a, b;
if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
return NULL;
}
return Py_BuildValue("i", a + b);
}
這個函數接受兩個Python對象作為輸入,從它們中提取兩個整數,將它們相加,然後將結果作為Python對象返回。它就像C和Python之間的翻譯員。
方法映射表
static PyMethodDef MyMethods[] = {
{"add", add_numbers, METH_VARARGS, "Add two numbers."},
{NULL, NULL, 0, NULL}
};
這個表就像我們Python模塊的菜單。它告訴Python,“這個模塊中有哪些函數可用。”在這裡,我們提供了一個名為“add”的函數。
初始化函數
PyMODINIT_FUNC PyInit_mymodule(void) {
return PyModule_Create(&mymodule);
}
當Python導入我們的模塊時,會調用這個函數。這就像新店開張一樣——它設置一切並使我們的模塊準備好使用。
建立和安裝擴展
現在我們已經寫了擴展,我們需要建立它。這個過程將我們的C代碼轉化為Python可以使用的東西。這就像烤蛋糕一樣——我們已經混合了配料,現在我們需要把它放進烤箱。
我們通常使用一個setup.py
文件來做到這一點:
from distutils.core import setup, Extension
module = Extension('mymodule', sources = ['mymodule.c'])
setup(name = 'MyModule',
version = '1.0',
description = 'This is a demo package',
ext_modules = [module])
要建立擴展,您需要運行:
python setup.py build
導入擴展
建立後,您可以使用新的模塊就像任何其他Python模塊一樣:
import mymodule
result = mymodule.add(5, 3)
print(result) # 輸出:8
這不酷嗎?你剛剛在Python中使用了C函數!
從Python傳遞函數參數
讓我們更多地談談如何從Python傳遞參數到C。記得這一行嗎?
if (!PyArg_ParseTuple(args, "ii", &a, &b))
PyArg_ParseTuple函數
這個函數是理解如何傳遞參數的關鍵。它就像海關官員,檢查和處理從Python到我們C函數的一切。
函數中的"ii"告訴它期望兩個整數。如果你想要傳遞一個字符串和一個浮點數,你會使用"sf" instead。以下是一個方便的格式指定符表:
格式指定符 | Python類型 | C類型 |
---|---|---|
i | int | int |
l | long | long |
f | float | float |
d | float | double |
s | str | char* |
O | any object | PyObject* |
返回值
正如我們需要謹慎處理進來的數據一樣,我們也需要正確包裝我們的返回值。
Py_BuildValue函數
這個函數就像我們C值的禮物包裝器,使它們對Python來說變得漂亮。以下它是如何工作的:
return Py_BuildValue("i", a + b);
"i"告訴Py_BuildValue創建一個整數對象。如果我們想要返回一個字符串,我們會使用"s"。
就這樣!你剛剛踏入了Python擴展的世界。記住,練習成就完美。嘗試編寫自己的簡單擴展,玩弄不同的數據類型,最重要的是,玩得開心!
Python擴展打開了無窮的可能性,讓你優化代碼的關鍵部分或與現有的C庫接口。這是你編程工具箱中的一個強大工具。
開心編程,直到下次,繼續探索和學習!
Credits: Image by storyset