Cython数据类型

Cython中,声明数据类型的主要是使用cdef语句,比如声明变量、函数和扩展静态类型等。

变量

首先启动Jupyter notebook,并导入Cython扩展:

1
2
$ jupyter notebook
In [1]: %load_ext Cython

声明变量类型时,在变量名前加入关键字cdef和类型,同一cdef语句中,可声明多个变量,还可对变量进行初始化,比如:

1
2
cdef int i
cdef double i, j = 2.0, k =3.0

声明类型后,将有严格的类型检查,比如:

1
2
3
In [2]: %%cython
cdef int i
i = 2.0

该种行为将导致报错:

1
2
3
4
5
6
7
8
9
Error compiling Cython file:
------------------------------------------------------------
...
cdef int i
i = 2.0
^
------------------------------------------------------------

Cannot assign type 'double' to 'int'

当需要强制类型转换时,只需要使用<目标类型>:

1
2
3
4
5
6
In [2]: %%cython
cdef int a = 1
cdef double b
b = <double> a
print(b)
1.0

以Fibonacci为例,看一下使用Cython后的速度提升:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
In [2]: %%cython
def fib_cython(n):
cdef int a = 0, b = 1
while b < n:
print(b, end=' ')
a, b = b, a + b
print()

In [3]: def fib_python(n):
a, b = 0, 1
while b < n:
print(b, end=' ')
a, b = b, a + b
print()

In [4]: %timeit fib_cython(10)
%timeit fib_python(10)
92 ns ± 0.652 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
285 ns ± 1.47 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

函数

Cython中的函数,必须使用cdef语句声明函数的返回类型:

1
2
cdef int max_cython(int a, int b):
return a if a > b else b

但该种方式只能在Cython中使用,不过Cython可以定义在Python中调用且可转换为高性能C语言函数的函数,此时使用关键字cpdef将生成两个版本:可供解释器使用的Python版本;可在Cython中使用的快速的C语言函数:

1
2
cdef int max_cython(int a, int b):
return a if a > b else b

声明扩展类型,需要使用cdef class语句,显式地声明要在编译期间使用的变量的类型。在类方法中访问声明的属性时,Cython将绕过开销很大的属性查找,直接访问底层C语言结构体中的指定字段。如果想要在Python代码中访问属性,必须在属性声明中使用限定符public或readonly。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
In [5]:%%cython
cdef class Point:
cdef public double x
cdef public double y
def __init__(self, double x, double y):
self.x = x
self.y = y

cdef double norm(Point p):
return (p.x**2 + p.y**2)**0.5

In [6]: aim = Point(1.0, 2.0)
In [7]: aim.x
Out[7]: 1.0

Cython中有关变量、函数、类的学习暂时就这些😃

0%