cython 笔记

数据类型

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隐藏了,只能解释器才能操作指针。

结构体数组

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

image

参考文档:
https://www.cnblogs.com/traditional/p/13246471.html

posted @ 2024-06-26 23:19  一枚码农  阅读(4)  评论(0编辑  收藏  举报