前言:這遍文章,是翻譯自官方文檔,覺得原官方文檔的例子有些抽象,所以我用一些具體的示例代碼替換了。
Python作為一種動(dòng)態(tài)語言, 它鼓勵(lì)的編程風(fēng)格優(yōu)先考慮類和對(duì)象的方法和屬性方面,而不是它們?nèi)绾芜m合哪種類繼承結(jié)構(gòu)。
這可以使Python成為一種非常輕松和舒適的快速開發(fā)語言,但需要付出代價(jià) - 管理數(shù)據(jù)類型的繁重工作會(huì)被轉(zhuǎn)嫁到解釋器上。在運(yùn)行時(shí),解釋器需要搜索命名空間,獲取屬性以及解析參數(shù)和關(guān)鍵字元組方面會(huì)消耗大量的時(shí)間。這種運(yùn)行時(shí)“后期綁定”是Python相對(duì)緩慢的主要原因。而Cython就使用類似于C++"早期綁定的"技術(shù),并且保留了大部分C/C++的特性,在編譯靜態(tài)版本的擴(kuò)展庫后,速度基本上等同于C/C++的運(yùn)行速度.
C變量和類型定義
cdef語句用于聲明C變量,無論是本地變量還是模塊級(jí)變量:
cdef int age;
cdef float score;
//聲明一個(gè)結(jié)構(gòu)體
cdef struct Person:
int age
char* name
#end-cdef
注意Structs可以聲明為cdef packed struct,它與C指令具有相同的效果
結(jié)構(gòu)體的初始化
- 使用struct的字面量進(jìn)行初始化
cdef Person p
p=Person(23,"Lisa")
- 使用類似關(guān)鍵的參數(shù)方式進(jìn)行初始化
cdef Person p
p=Person(age=23,name="Lisa")
- 使用Python的dict進(jìn)行賦值,這將使用Cython的自動(dòng)轉(zhuǎn)換功能對(duì)結(jié)構(gòu)體逐個(gè)成員賦值。 請(qǐng)注意,這涉及更多的Python開銷
cdef Person p
p={"age":23,"name":"Lisa"}
目前沒有用于定義常量的特殊語法,但您可以為此目的使用匿名枚舉聲明,例如:
cdef enum:
OPEN=1
CLOSE=0
#end-cdef
注意:struct,union和enum僅在定義類型時(shí)使用,而不是在引用它時(shí)使用。 例如,要聲明一個(gè)指向Person的指針變量,你會(huì)寫:
cdef struct Person:
char* name
int age
#end-cdef
/**正確寫法**/
cdef Person *jk
/*錯(cuò)誤寫法*/
cdef struct Person *jk
cdef 還可以用于聲明屬于c / cython的函數(shù)
cdef int add(int a,int b):
return a+b
#end-cdef
Cython中有三種函數(shù)定義:
- def:Python函數(shù)是使用def語句定義的,就像在Python中一樣。它們將Python對(duì)象作為參數(shù)并返回Python對(duì)象。
- cdef:Cython函數(shù)使用新的cdef語句定義。它們將Python對(duì)象或C值作為參數(shù),并且可以返回Python對(duì)象或C值。
- cpdef:Hybrid函數(shù)(別以為是某田的混動(dòng)技術(shù)-___,-),允許從任何地方調(diào)用cpdef聲明的混合函數(shù),但在從其他Cython代碼調(diào)用時(shí)Hybrid函數(shù)會(huì)獲得C一樣的速度。
即使從Cython調(diào)用,也可以通過子類或?qū)嵗龑傩陨系腜ython方法覆蓋cpdef聲明的方法或?qū)傩?/strong>。如果發(fā)生這種情況,就得不到性能的提升,即使它沒有被覆蓋,跟調(diào)用cdef方法相比,從Cython調(diào)用cpdef方法的開銷很小,可以忽略不計(jì)。
Cython函數(shù)中的參數(shù)
可以使用常規(guī)C聲明語法將任一類型的函數(shù)的參數(shù)聲明為具有C數(shù)據(jù)類型。 例如:
當(dāng)Python函數(shù)的參數(shù)聲明為具有C數(shù)據(jù)類型時(shí),它將作為Python對(duì)象傳入,并在可能的情況下自動(dòng)轉(zhuǎn)換為C值。 請(qǐng)看如下示例:
//python函數(shù)
def eat(int n,char* food):
return f'今天我吃了{(lán)n}次{food}'
#end-def
/*等價(jià)于*/
def eat(n,food):
cdef int i=n
cdef char* food=food
return f'今天我吃了{(lán)n}次{food}'
#end-def
目前,只能對(duì)數(shù)字類型,字符串類型和結(jié)構(gòu)體進(jìn)行自動(dòng)轉(zhuǎn)換(以遞歸方式組合任何這些類型); 嘗試將任何其他類型用于Python函數(shù)的參數(shù)將導(dǎo)致編譯時(shí)錯(cuò)誤。在處理字符串的時(shí)候,在調(diào)用一個(gè)引用后必須確保該指針是否正被用, 可以從Python映射中獲取結(jié)構(gòu),如果要在函數(shù)返回后,在處理字符串的時(shí)候,必須確保該指針是否正在使用。另一方面,Cython函數(shù)可以具有任何類型的參數(shù),因?yàn)樗鼈兪鞘褂闷胀ǖ腃函數(shù)調(diào)用直接傳遞的。
使用帶有Python對(duì)象返回類型的cdef聲明的函數(shù)(如Python函數(shù)),當(dāng)執(zhí)行離開函數(shù)體而沒有顯式返回值時(shí),將返回None值。這與C / C ++形成對(duì)比,后者使返回值未定義。 在非Python對(duì)象返回類型的情況下,返回等價(jià)于零的值,例如,0表示int,F(xiàn)alse表示bint,NULL表示指針類型。