# 早期綁定速度
> 原文: [http://docs.cython.org/en/latest/src/userguide/early_binding_for_speed.html](http://docs.cython.org/en/latest/src/userguide/early_binding_for_speed.html)
作為一種動態語言,Python 鼓勵一種編程風格,即在方法和屬性方面考慮類和對象,而不是它們適合類層次結構。
這可以使 Python 成為一種非常輕松和舒適的快速開發語言,但需要付出代價 - 管理數據類型的“繁文縟節”會被轉儲到解釋器上。在運行時,解釋器在搜索命名空間,獲取屬性以及解析參數和關鍵字元組方面做了大量工作。與“早期綁定”語言(如 C ++)相比,這種運行時“后期綁定”是 Python 相對緩慢的主要原因。
然而,使用 Cython,通過使用“早期綁定”編程技術可以獲得顯著的加速。
例如,考慮以下(愚蠢)代碼示例:
```py
cdef class Rectangle:
cdef int x0, y0
cdef int x1, y1
def __init__(self, int x0, int y0, int x1, int y1):
self.x0 = x0
self.y0 = y0
self.x1 = x1
self.y1 = y1
def area(self):
area = (self.x1 - self.x0) * (self.y1 - self.y0)
if area < 0:
area = -area
return area
def rectArea(x0, y0, x1, y1):
rect = Rectangle(x0, y0, x1, y1)
return rect.area()
```
在`rectArea()`方法中,對`rect.area()`和`area()`方法的調用包含大量的 Python 開銷。
但是,在 Cython 中,在 Cython 代碼中發生調用的情況下,可以消除大量的開銷。例如:
```py
cdef class Rectangle:
cdef int x0, y0
cdef int x1, y1
def __init__(self, int x0, int y0, int x1, int y1):
self.x0 = x0
self.y0 = y0
self.x1 = x1
self.y1 = y1
cdef int _area(self):
area = (self.x1 - self.x0) * (self.y1 - self.y0)
if area < 0:
area = -area
return area
def area(self):
return self._area()
def rectArea(x0, y0, x1, y1):
cdef Rectangle rect = Rectangle(x0, y0, x1, y1)
return rect._area()
```
這里,在 Rectangle 擴展類中,我們定義了兩種不同的區域計算方法,即高效的`_area()` C 方法,以及 Python 可調用的`area()`方法,它作為`_area()`的薄包裝器。還要注意函數`rectArea()`我們如何'早期綁定',通過聲明顯式賦予 Rectangle 類型的局部變量`rect`。通過使用此聲明,我們獲得了訪問更有效的 C-callable `_area()`方法的能力,而不僅僅是動態分配給`rect`。
但是 Cython 通過允許我們聲明雙訪問方法 - 可以在 C 級別高效調用的方法,但也可以以 Python 訪問開銷為代價從純 Python 代碼訪問,從而再次為我們提供了更多的簡單性。考慮以下代碼:
```py
cdef class Rectangle:
cdef int x0, y0
cdef int x1, y1
def __init__(self, int x0, int y0, int x1, int y1):
self.x0 = x0
self.y0 = y0
self.x1 = x1
self.y1 = y1
cpdef int area(self):
area = (self.x1 - self.x0) * (self.y1 - self.y0)
if area < 0:
area = -area
return area
def rectArea(x0, y0, x1, y1):
cdef Rectangle rect = Rectangle(x0, y0, x1, y1)
return rect.area()
```
在這里,我們只有一個區域方法,聲明為 [`cpdef`](language_basics.html#cpdef) ,使其可以作為 C 函數有效地調用,但仍然可以從純 Python(或后期綁定的 Cython)代碼訪問。
如果在 Cython 代碼中,我們有一個已經'早期綁定'的變量(即,顯式聲明為 Rectangle 類型,或者轉換為 Rectangle 類型),那么調用其 area 方法將使用高效的 C 代碼路徑并跳過 Python 開銷。但是如果在 Cython 或常規 Python 代碼中我們有一個存儲 Rectangle 對象的常規對象變量,那么調用 area 方法將需要:
* 區域方法的屬性查找
* 打包參數的元組和關鍵字的 dict(在這種情況下都是空的)
* 使用 Python API 調用該方法
并且在區域方法本身內:
* 解析元組和關鍵字
* 執行計算代碼
* 將結果轉換為 python 對象并返回它
因此,在 Cython 中,通過在聲明和轉換變量中使用強類型來實現大規模優化是可能的。對于使用方法調用的緊密循環,以及這些方法是純 C 的情況,差異可能很大。
- Cython 3.0 中文文檔
- 入門
- Cython - 概述
- 安裝 Cython
- 構建 Cython 代碼
- 通過靜態類型更快的代碼
- Tutorials
- 基礎教程
- 調用 C 函數
- 使用 C 庫
- 擴展類型(又名.cdef 類)
- pxd 文件
- Caveats
- Profiling
- Unicode 和傳遞字符串
- 內存分配
- 純 Python 模式
- 使用 NumPy
- 使用 Python 數組
- 進一步閱讀
- 相關工作
- 附錄:在 Windows 上安裝 MinGW
- 用戶指南
- 語言基礎
- 擴展類型
- 擴展類型的特殊方法
- 在 Cython 模塊之間共享聲明
- 與外部 C 代碼連接
- 源文件和編譯
- 早期綁定速度
- 在 Cython 中使用 C ++
- 融合類型(模板)
- 將 Cython 代碼移植到 PyPy
- Limitations
- Cython 和 Pyrex 之間的區別
- 鍵入的內存視圖
- 實現緩沖協議
- 使用并行性
- 調試你的 Cython 程序
- 用于 NumPy 用戶的 Cython
- Pythran 作為 Numpy 后端