cython 筆記

一枚码农發表於2024-06-26

資料型別

image

# bool 型別
// bool_type_ptactice.pyx
cdef bint a = 123  # 非0 為 真 , 0 為假
cdef bint b = -123
cdef bint c = 0
py_a = a   # cdef 定義的內容沒法直接在python中直接引用
py_b = b
py_c = c

// main.py
import pyximport
pyximport.install(language_level=3)

import bool_type_ptactice
print(bool_type_ptactice.py_a)
print(bool_type_ptactice.py_b)
print(bool_type_ptactice.py_c)

>>>
True
True
False


# int 型別
python3中int是沒有範圍限制的,cython中會有型別轉換如果溢位會報錯

# float 型別
python中的對應cython中的double,所以可以放心使用

# bytes 或 str 型別
// bytes_practice.pyx
cdef bytes name_b = b'cython'  # 建立位元組使用bytes
cdef str name_s = 'cython'  # 建立字串使用str 與python一樣
cdef unicode name_u = u'cython'  # 與使用str效果等價,使用unicode是前邊必須要有u,主要是為了相容python2
py_name_b = name_b
py_name_s = name_s
py_name_u = name_u

//main.py
import pyximport
pyximport.install(language_level=3)

import bytes_practice

print(bytes_practice.py_name_b)
print(bytes_practice.py_name_s)
print(bytes_practice.py_name_u)

>>>
b'cython'
cython
cython


# 使用python型別進行靜態申明
除了C中的資料型別,在cython中還可以使用python中內建的所有資料型別進行靜態宣告
//py_data_type_practices.pyx
cdef tuple ta =(1, 2)
cdef list la =  [1,2,3]
cdef dict da = {'name': 'cython'}
cdef set sa = {'cython', 'python'}
cdef frozenset fa = frozenset(['1','1', '3', '5'])
py_tuple = ta  # 這裡雖然是將cython變數賦值給python變數 但他們其實是同一個變數
py_list = la   # 他們是等價的,所以python變數所支援的操作,在cython中照樣支援
py_dict = da  # 比如insert(), append()等
py_set = sa
py_frozenset = fa
print('cython 物件與 python 物件是同一個嗎?:', ta is py_tuple)

//main.py
import pyximport
pyximport.install(language_level=3)

import py_data_type_practices
print(py_data_type_practices.py_tuple)
print(py_data_type_practices.py_list)
print(py_data_type_practices.py_dict)
print(py_data_type_practices.py_set)
print(py_data_type_practices.py_frozenset)


>>>
cython 物件與 python 物件是同一個嗎?: True
(1, 2)
[1, 2, 3]
{'name': 'cython'}
{'python', 'cython'}
frozenset({'3', '5', '1'})

在cython中使用python內建型別做靜態申明的時候,如果沒有賦初始值,預設都是None,但是int和float除外(這倆實際上用的是c的型別)。

為什麼 Cython 可以做到這一點呢?實際上這些結構在 CPython 中都是已經實現好了的,Cython 將它們設定為指向底層中某個資料結構的 C 指標,比如:cdef tuple a,那麼 a 就是一個PyTupleObject *,它們可以像普通變數一樣使用,當然 Python 中的變數也是一樣的,a = tuple(),那麼 a 同樣是一個 PyTupleObject *。

python內建型別是沒法用來申明指標的哦!!!

指標

與C中的申明方式一樣,
cdef int *a = 0
獲取指標指向的記憶體地址不用*,*在python中被佔用了(*args, **kwargs, 以及用*拆包)用下表的方式
a[0] = 1

例如:
//pointer_practice.pyx
cdef double a = 3.14
cdef double *b = &a

print(f'a = {a}')

b[0] = 6.66
print(f'update after: a = {a}')


// main.py
import pyximport
pyximport.install(language_level=3)

import pointer_practice

>>>
a = 3.14
update after: a = 6.66


在cython中我們不能在函式中返回一個指標,列印某個指標以及指標作為某個python動態資料結構的成員,
因為在python中沒有指標這個概念或者被python隱藏了,只能直譯器才能操作指標。

參考文件:
https://www.cnblogs.com/traditional/p/13246471.html