数据类型
# 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隐藏了,只能解释器才能操作指针。
结构体数组
from cpython.mem cimport PyMem_Malloc, PyMem_Free
ctypedef struct Point:
long x,
long y
cpdef struct_array():
# malloc memory
cdef:
int i, length = 3
Point *array = <Point *> PyMem_Malloc(length * sizeof(Point))
# assignment value
for i in range(length):
array[i].x = i
array[i].y = i
# print
for i in range(length):
print(f'struct {i} point value [{array[i].x}, {array[i].y}]')
PyMem_Free(array)
return True
cpdef common_array():
cdef:
int i = 0, length = 3
char *array[3]
for i in range(length):
array[i] = 'a'
print('common array', array)
return True
参考文档:
https://www.cnblogs.com/traditional/p/13246471.html