# 擴展類型的特殊方法
> 原文: [http://docs.cython.org/en/latest/src/userguide/special_methods.html](http://docs.cython.org/en/latest/src/userguide/special_methods.html)
本頁介紹了 Cython 擴展類型當前支持的特殊方法。所有特殊方法的完整列表顯示在底部的表格中。其中一些方法的行為與 Python 對應方式不同,或者沒有直接的 Python 對應方式,需要特別提及。
注意
此頁面上說的所有內容僅適用于使用`cdef class`語句定義的擴展類型。它不適用于使用 Python [`class`](https://docs.python.org/3/reference/compound_stmts.html#class "(in Python v3.7)") 語句定義的類,其中適用普通的 Python 規則。
## 聲明
必須使用 [`def`](https://docs.python.org/3/reference/compound_stmts.html#def "(in Python v3.7)") 而不是 [`cdef`](language_basics.html#cdef) 聲明擴展類型的特殊方法。這不會影響它們的性能 - Python 使用不同的調用約定來調用這些特殊方法。
## Docstrings
目前,某些擴展類型的特殊方法并未完全支持 docstrings。您可以在源中放置 docstring 作為注釋,但在運行時它不會顯示在相應的`__doc__`屬性中。 (這似乎是一個 Python 限制 - 在 <cite>PyTypeObject</cite> 數據結構中沒有任何地方放置這樣的文檔字符串。)
## 初始化方法:`__cinit__()`和`__init__()`
初始化對象有兩種方法。
您應該在`__cinit__()`方法中執行對象的基本 C 級初始化,包括分配您的對象將擁有的任何 C 數據結構。您需要注意在`__cinit__()`方法中執行的操作,因為在調用對象時,該對象可能還不是完全有效的 Python 對象。因此,您應該小心地調用可能觸及該對象的任何 Python 操作;特別是它的方法和任何可以被子類型覆蓋的東西(因此依賴于它們已經初始化的子類型狀態)。
在調用`__cinit__()`方法時,已為該對象分配了內存,并且已將其初始化為 0 或 null 的任何 C 屬性。 (任何 Python 屬性也已初始化為 None,但您可能不應該依賴它。)保證您的`__cinit__()`方法只能被調用一次。
如果擴展類型具有基類型,則在`__cinit__()`方法之前會自動調用基類型層次結構中的任何現有`__cinit__()`方法。您無法顯式調用繼承的`__cinit__()`方法,基類型可以自由選擇是否實現`__cinit__()`。如果需要將修改后的參數列表傳遞給基類型,則必須在`__init__()`方法中執行初始化的相關部分,而不是調用繼承方法的常規規則。
任何無法在`__cinit__()`方法中安全完成的初始化都應在`__init__()`方法中完成。到`__init__()`被調用時,該對象是一個完全有效的 Python 對象,所有操作都是安全的。在某些情況下,可能會多次調用`__init__()`或根本不調用`__init__()`,因此在這種情況下,您的其他方法應該設計得很穩健。
傳遞給構造函數的任何參數都將傳遞給`__cinit__()`方法和`__init__()`方法。如果你期望在 Python 中繼承你的擴展類型,你可能會發現給`__cinit__()`方法 <cite>*</cite> 和 <cite>**</cite> 參數是有用的,這樣它就可以接受并忽略額外的參數。否則,任何具有不同簽名的`__init__()`的 Python 子類都必須覆蓋`__new__()` [[1]](#id4) 以及`__init__()`,Python 類的編寫者不會期望得做。或者,為方便起見,如果您聲明`__cinit__`()`方法不帶參數(除了 self),它將忽略傳遞給構造函數的任何額外參數,而不會抱怨簽名不匹配。
Note
所有構造函數參數都將作為 Python 對象傳遞。這意味著不可轉換的 C 類型(如指針或 C ++對象)無法從 Cython 代碼傳遞到構造函數中。如果需要,請使用工廠函數來處理對象初始化。直接調用此函數中的`__new__()`以繞過對`__init__()`構造函數的調用通常會有所幫助。
有關示例,請參閱現有 C / C ++指針 中的 [實例化。](extension_types.html#existing-pointers-instantiation)
<colgroup><col class="label"><col></colgroup>
| [[1]](#id3) | [https://docs.python.org/reference/datamodel.html#object.__new__](https://docs.python.org/reference/datamodel.html#object.__new__) |
## 定稿方法:`__dealloc__()`
`__cinit__()`方法的對應物是`__dealloc__()`方法,它應該執行`__cinit__()`方法的反轉。您`__cinit__()`方法中明確分配的任何 C 數據(例如通過 malloc)都應該在`__dealloc__()`方法中釋放。
您需要注意在`__dealloc__()`方法中執行的操作。在調用`__dealloc__()`方法時,對象可能已經被部分破壞,并且就 Python 而言可能不處于有效狀態,因此您應該避免調用可能觸及該對象的任何 Python 操作。特別是,不要調用對象的任何其他方法或做任何可能導致對象復活的事情。如果你堅持只是解除分配 C 數據是最好的。
您無需擔心釋放對象的 Python 屬性,因為在`__dealloc__()`方法返回后,Cython 將為您完成此操作。
在對擴展類型進行子類化時,請注意,即使重寫了超類的`__dealloc__()`方法,也始終會調用它。這與典型的 Python 行為形成對比,在這種行為中,除非子類顯式調用超類方法,否則不會執行超類方法。
Note
擴展類型沒有`__del__()`方法。
## 算術方法
算術運算符方法(如`__add__()`)的行為與 Python 對應方法不同。這些方法沒有單獨的“反向”版本(`__radd__()`等)。相反,如果第一個操作數不能執行操作,則調用第二個操作數的相同方法,操作數的順序相同。
這意味著您不能依賴這些方法的第一個參數是“自”或正確的類型,并且您應該在決定做什么之前測試兩個操作數的類型。如果您無法處理已經給出的類型組合,則應返回 <cite>NotImplemented</cite> 。
這也適用于就地算術方法`__ipow__()`。它不適用于任何其他始終將 <cite>self</cite> 作為第一個參數的原位方法(`__iadd__()`等)。
## 豐富的比較
有兩種方法可以實現比較方法。根據應用程序的不同,這種方式可能更好:
* 第一種方法使用 6 Python [特殊方法](https://docs.python.org/3/reference/datamodel.html#basic-customization) `__eq__()`,`__lt__()`等。這是 Cython 0.27 以來的新功能,與普通 Python 類完全一樣。
* 第二種方法使用單一特殊方法`__richcmp__()`。這在一個方法中實現了所有豐富的比較操作。簽名是`def __richcmp__(self, other, int op)`。整數參數`op`表示要執行的操作,如下表所示:
<colgroup><col width="42%"> <col width="58%"></colgroup>
| &LT; | Py_LT |
| == | Py_EQ |
| &GT; | Py_GT |
| &LT = | Py_LE |
| != | Py_NE |
| &GT; = | Py_GE |
這些常量可以從`cpython.object`模塊中導入。
## `__next__()`方法
希望實現迭代器接口的擴展類型應該定義一個名為`__next__()`的方法,而不是下一個方法。 Python 系統將自動提供調用`__next__()`的下一個方法。 _NOT_ 是否明確地給你的類型一個`next()`方法,否則可能會發生壞事。
## 特殊方法表
此表列出了所有特殊方法及其參數和返回類型。在下表中,self 的參數名稱用于指示參數具有方法所屬的類型。表中未指定類型的其他參數是通用 Python 對象。
您不必將方法聲明為采用這些參數類型。如果您聲明了不同的類型,則會根據需要執行轉換。
### 一般
[https://docs.python.org/3/reference/datamodel.html#special-method-names](https://docs.python.org/3/reference/datamodel.html#special-method-names)
<colgroup><col width="18%"> <col width="30%"> <col width="10%"> <col width="41%"></colgroup>
| 名稱 | 參數 | 返回類型 | 描述 |
| --- | --- | --- | --- |
| __cinit__ | 自我,...... | | 基本初始化(沒有直接的 Python 等價物) |
| __ 在里面 __ | self, … | ? | 進一步初始化 |
| __dealloc__ | 自 | ? | 基本的釋放(沒有直接的 Python 等價物) |
| __cmp__ | x,y | INT | 3 路比較(僅限 Python 2) |
| __str__ | self | 賓語 | STR(個體經營) |
| __repr__ | self | object | 再版(個體經營) |
| __hash__ | self | Py_hash_t | 散列函數(返回 32/64 位整數) |
| __ 呼叫 __ | self, … | object | 自(…) |
| __iter__ | self | object | 返回序列的迭代器 |
| __getattr__ | 自我,名字 | object | 獲取屬性 |
| __getattribute__ | self, name | object | 無條件地獲取屬性 |
| __setattr__ | 自我,名字,val | ? | 設置屬性 |
| __delattr__ | self, name | ? | 刪除屬性 |
### 豐富的比較運算符
[https://docs.python.org/3/reference/datamodel.html#basic-customization](https://docs.python.org/3/reference/datamodel.html#basic-customization)
您可以選擇實現標準的 Python 特殊方法,如`__eq__()`或單個特殊方法`__richcmp__()`。根據應用,一種方式或另一種方式可能更好。
<colgroup><col width="18%"> <col width="30%"> <col width="10%"> <col width="43%"></colgroup>
| Name | Parameters | Return type | Description |
| --- | --- | --- | --- |
| __eq__ | 自我,是的 | object | 自我== y |
| __ne__ | self, y | object | self!= y(如果沒有,則回退到`__eq__`) |
| __lt__ | self, y | object | 自我&lt; ? |
| __gt__ | self, y | object | 自我&gt; ? |
| __le__ | self, y | object | 自我&lt; = y |
| __ge__ | self, y | object | 自我&gt; = y |
| __richcmp__ | self,y,int op | object | 為上述所有內容加入了豐富的比較方法(沒有直接的 Python 等價物) |
### 算術運算符
[https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types](https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types)
<colgroup><col width="18%"> <col width="30%"> <col width="10%"> <col width="41%"></colgroup>
| Name | Parameters | Return type | Description |
| --- | --- | --- | --- |
| __ 加 __ | x, y | object | 二進制 <cite>+</cite> 運算符 |
| __sub__ | x, y | object | 二進制 <cite>-</cite> 運算符 |
| __mul__ | x, y | object | <cite>*</cite> 運算符 |
| __div__ | x, y | object | <cite>/</cite> 運算符用于舊式劃分 |
| __floordiv__ | x, y | object | <cite>//</cite> 運算符 |
| __truediv__ | x, y | object | <cite>/</cite> 運算符用于新式劃分 |
| __mod__ | x, y | object | <cite>%</cite>運算符 |
| __divmod__ | x, y | object | 組合 div 和 mod |
| __pow__ | x,y,z | object | <cite>**</cite> 運算符或 pow(x,y,z) |
| __neg__ | self | object | 一元 <cite>-</cite> 運算符 |
| __pos__ | self | object | 一元 <cite>+</cite> 運算符 |
| __abs__ | self | object | 絕對值 |
| __nonzero__ | self | int | 轉換為布爾值 |
| __ 倒置 __ | self | object | <cite>?</cite>運算符 |
| __lshift__ | x, y | object | <cite>&lt;&lt;</cite> 運營商 |
| __rshift__ | x, y | object | <cite>&gt;&gt;</cite> 運營商 |
| __ 和 __ | x, y | object | <cite>&amp;</cite> 運營商 |
| __ 要么 __ | x, y | object | <cite>|</cite> 運營商 |
| __xor__ | x, y | object | <cite>^</cite> 運算符 |
### 數字轉換
[https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types](https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types)
<colgroup><col width="18%"> <col width="30%"> <col width="10%"> <col width="41%"></colgroup>
| Name | Parameters | Return type | Description |
| --- | --- | --- | --- |
| __int__ | self | object | 轉換為整數 |
| __ 長 __ | self | object | 轉換為長整數 |
| __ 浮動 __ | self | object | 轉換為浮動 |
| __oct__ | self | object | 轉換為八進制 |
| __hex__ | self | object | 轉換為十六進制 |
| __index__(僅限 2.5+) | self | object | 轉換為序列索引 |
### 就地算術運算符
[https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types](https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types)
<colgroup><col width="18%"> <col width="30%"> <col width="10%"> <col width="41%"></colgroup>
| Name | Parameters | Return type | Description |
| --- | --- | --- | --- |
| __ 我加 __ | 自我,x | object | <cite>+ =</cite> 運算符 |
| __isub__ | self, x | object | <cite>- =</cite> 運算符 |
| __imul__ | self, x | object | <cite>* =</cite> 運算符 |
| __idiv__ | self, x | object | <cite>/ =</cite> 運算符用于舊式劃分 |
| __ifloordiv__ | self, x | object | <cite>// =</cite> 運算符 |
| __truediv__ | self, x | object | <cite>/ =</cite> 運算符用于新式劃分 |
| __imod__ | self, x | object | <cite>%=</cite> 運算符 |
| __pow__ | x, y, z | object | <cite>** =</cite> 運算符 |
| __ilshift__ | self, x | object | <cite>&lt;&lt; =</cite> 運算符 |
| __irshift__ | self, x | object | <cite>&gt;&gt; =</cite> 運算符 |
| __ 我和 __ | self, x | object | <cite>&amp; =</cite> 運算符 |
| __ior__ | self, x | object | <cite>| =</cite> 運算符 |
| __ixor__ | self, x | object | <cite>^ =</cite> 運算符 |
### 序列和映射
[https://docs.python.org/3/reference/datamodel.html#emulating-container-types](https://docs.python.org/3/reference/datamodel.html#emulating-container-types)
<colgroup><col width="18%"> <col width="30%"> <col width="10%"> <col width="41%"></colgroup>
| Name | Parameters | Return type | Description |
| --- | --- | --- | --- |
| __len__ | self | Py_ssize_t | LEN(個體經營) |
| __getitem__ | self, x | object | 自[X] |
| __setitem__ | 自我,x,y | ? | self [x] = y |
| __delitem__ | self, x | ? | del self [x] |
| __getslice__ | self,Py_ssize_t i,Py_ssize_t j | object | 自[I:j]的 |
| __setslice__ | self,Py_ssize_t i,Py_ssize_t j,x | ? | 自我[i:j] = x |
| __delslice__ | self, Py_ssize_t i, Py_ssize_t j | ? | del self [i:j] |
| __contains__ | self, x | int | x 在自我中 |
### 迭代器
[https://docs.python.org/3/reference/datamodel.html#emulating-container-types](https://docs.python.org/3/reference/datamodel.html#emulating-container-types)
<colgroup><col width="18%"> <col width="30%"> <col width="10%"> <col width="41%"></colgroup>
| Name | Parameters | Return type | Description |
| --- | --- | --- | --- |
| __ 下一個 __ | self | object | 獲取下一個項目(在 Python 中稱為 next) |
### 緩沖接口[ [**PEP 3118** ](https://www.python.org/dev/peps/pep-3118)](沒有 Python 當量 - 見注 1)
<colgroup><col width="18%"> <col width="30%"> <col width="10%"> <col width="41%"></colgroup>
| Name | Parameters | Return type | Description |
| --- | --- | --- | --- |
| __getbuffer__ | self,Py_buffer <cite>* view</cite> ,int flags | ? | ? |
| __releasebuffer__ | self,Py_buffer <cite>* view</cite> | ? | ? |
### 緩沖接口[遺留](沒有 Python 等價物 - 見注 1)
<colgroup><col width="18%"> <col width="30%"> <col width="10%"> <col width="41%"></colgroup>
| Name | Parameters | Return type | Description |
| --- | --- | --- | --- |
| __getreadbuffer__ | self,Py_ssize_t i,void <cite>** p</cite> | ? | ? |
| __getwritebuffer__ | self, Py_ssize_t i, void <cite>**p</cite> | ? | ? |
| __getsegcount__ | self,Py_ssize_t <cite>* p</cite> | ? | ? |
| __getcharbuffer__ | self,Py_ssize_t i,char <cite>** p</cite> | ? | ? |
### 描述符對象(見注 2)
[https://docs.python.org/3/reference/datamodel.html#emulating-container-types](https://docs.python.org/3/reference/datamodel.html#emulating-container-types)
<colgroup><col width="18%"> <col width="30%"> <col width="10%"> <col width="41%"></colgroup>
| Name | Parameters | Return type | Description |
| --- | --- | --- | --- |
| __ 得到 __ | 自我,實例,階級 | object | 獲取屬性的值 |
| __ 組 __ | 自我,實例,價值 | ? | 設置屬性值 |
| __ 刪除 __ | 自我,實例 | ? | Delete attribute |
Note
(1)緩沖區接口旨在供 C 代碼使用,不能直接從 Python 訪問。它在 Python 2.x 的 Python / C API 參考手冊的 6.6 和 10.6 節中描述。它被 Python 2.6 中新的 [**PEP 3118** ](https://www.python.org/dev/peps/pep-3118)緩沖協議取代,并且在 Python 3 中不再可用。有關新 API 的操作指南,見 [實現緩沖協議](buffer.html#buffer) 。
Note
(2)描述符對象是新式 Python 類的支持機制的一部分。請參閱 Python 文檔中對描述符的討論。另見 [**PEP 252** ](https://www.python.org/dev/peps/pep-0252),“使類型看起來更像類”, [**PEP 253** ](https://www.python.org/dev/peps/pep-0253),“Subtyping Built-In Types”。
- 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 后端