Cython的C指针

与C一样,尽管指针性与变量而不是类型相关联,但可以在类型或变量附近声*号。

%%cython

cdef int *a

cdef int *b

但这样在变量a,b写在一行,cython编译器会发出警告的信息,因此建议每个变量单独声明

%%cython

cdef int *a,*b

Cython中的指针的解引操作

在Cython中解引用指针与在C语言中不同。

由于Python语言已经使用*args和**kwargs语法来允许任意位置和关键字参数并支持函数参数解包,因此Cython不支持*

*解引语法是C指针的语法。 取而代之的是,我们在位置0的指针处建立索引,以解引Cython中的指针的引用。 这种语法也可以解引C中的指针,尽管这种情况很少见。

Cython的结构体与指针

无论在C中使用箭头运算符的任何地方,在Cython中的结构体都使用点运算符访问其内部的成员变量,Cython将生成正确的C级代码

%%cython -a

cdef struct Person:

char* name

unsigned int age

#end-cdef

#初始化结构体

cdef Person p=Person("jck308",32)

#声明Person类型结构体指针p_per

#并将变量p的地址赋值给指针p_per

cdef Person *p_per=&p

#访问结构体的成员

print(p.age)

print(p.name)

print(p_per.age)

print(p_per.name)

混合静态和动态类型变量

Cython允许静态和动态类型变量之间的赋值。静态和动态的这种流体混合是一个强大的特性,我们将在多个实例中使用它:它允许我们对大多数代码基使用动态Python对象,并轻松地将它们转换为性能关键部分加速、静态类型的类比。

举例来说,假设我们有几个静态int,我们想将它们组合成(动态)Python元组。使用Python/C API创建和初始化这个元组的C代码很简单,但是很繁琐,需要几十行代码,并且需要大量的错误检查。在Cython,显而易见的方法就是:

%%cython

#静态类型的变量

cdef int a=1,b=2,c=3

##动态类型的变量

tuple_of_ints=(a,b,c)

print(tuple_of_ints)

这段代码很无聊。 这里要强调的一点是,a,b和c是静态类型的整数,而Cython允许使用它们创建动态类型的Python元组。 然后,我们可以将该元组分配给动态键入的tuple_of_ints变量。 该示例的简单性是Cython强大之处:我们可以以显而易见的方式创建一个C类型int元组,而无需进一步思考。 我们希望像这样的概念上简单的事情变得简单,这就是Cython所提供的。

此示例之所以有效,是因为C类型的int与Python int之间存在明显的对应关系,因此Python可以为我们自动类型转换。 例如,如果a,b和c是C指针,则此示例无法按原样工作。 在这种情况下,我们必须解引它们,然后再将它们放入元组或使用其他策略。

例如下面的代码是个错误的例子,因为Python解释器无法识别指针类型的变量

%%cython

cdef int k=55,j=56

cdef int *a=&k

cdef int *b=&j

tuple_of_ints=(a,b)

print(tuple_of_ints)

正确的做法,如下图所示,我们通过解引指针变量a、b

ss8.png

给出了内置Python类型与C或C ++类型之间对应关系的完整列表

ss8.png

Cythond的bint类型

bint布尔整数类型是C级别的int,并与Python的bool相互转换。 它具有真实性的标准C解释:零为False,非零为True。

整数类型转换和溢出

Python 3中,所有int对象都是无限精度的。当将整数类型从Python转换为C时,Cython会生成检查溢出的代码。 如果C类型不能表示Python整数,则会引发运行时OverflowError。

float类型转换

Python fload存储为C double。 根据IEEE 754转换规则,将Python浮点数转换为C浮点数可能会截断为0.0或正负无穷大。

Cython的double类型会被动态转换Python的float类型

%%cython

cdef double d=384848048282945060321.3835

b=d

print(b)

print(type(b))

ss8.png

Complex类定

The Python complex类型存储为两个double的C结构,Cython具有浮点复数和双复数C级类型,它们对应于Python复数类型。 C类型与Python复杂类型具有相同的接口,但是使用有效的C级操作。 这包括访问实数和虚数分量的实数和imag属性,创建多个复数共轭的共轭方法,以及用于加,减,乘和除的有效运算。C级Complex类型与C99 _Complex类型或C ++ std :: complex模板化类兼容。

bytes类型

Python字节类型会自动在char *或std :: string之间来回转换。下面示例就是Cython char类型指针 动态转换为Python的bytes

%%cython

cdef char* s="Hello World"

b=s

print(b)

print(type(b))

用Python类型静态声明变量

到目前为止,我们一直使用cdef静态声明C类型的变量。 也可以使用cdef静态声明Python类型的变量。 我们可以对内置类型(例如list,tuple和dict)执行此操作; 扩展类型,例如NumPy数组; 还有很多其他

并非所有的Python类型都可以静态声明:它们必须用C实现,并且Cython必须有权访问该声明。 内置的Python类型已经满足了这些要求,并且声明它们很简单。 例如Python典型的集合类型list,dict,str,set(str就是集合类型,字符串数组):

cdef list mylist

cdef dict mydi

cdef str pname

cdef set myset

此示例中的变量是完整的Python对象。 在后台,Cython将它们声明为指向某些内置Python结构类型的C指针。 它们可以像普通的Python变量一样使用,但是受其声明类型的约束:

%%cython

cdef list mylist=[k+1 for k in range(1,11)]

pylist=mylist

print("mylist:",mylist)

print("删除pylist索引2的元素")

del pylist[2]

print(mylist)

在这里,通过删除pylist第3个元素也会删除mylist的第3个元素,因为它们引用的是同一列表。mylist和pylist之间的一个区别是,mylist只能引用Python列表对象,而pylist可以引用任何Python类型。 Cython将在编译时和运行时对mylist施加类型约束。

备注:关于Cython更复杂的数组类型引用,可以参考此篇文章《第5篇:Cython的线性表性操作》

乍一看,Cython允许静态声明具有内置Python类型的变量似乎有些奇怪。 为什么不照常使用Python的动态类型? 答案指出了Cython的一般原理:我们提供的静态类型信息越多,Cython就能更好地优化结果。 像往常一样,该规则也有例外,但这通常是正确的。 例如,以下代码从Cython函数中返回sieveOfEratosthenes()返回一个cdef list的对象附加到动态类型的变量中:

%%cython

#cython:language_level=3

cpdef list sieveOfEratosthenes(int n):

cdef list pr = [True for i in range(n + 1)]

cdef int p = 2

cdef list res=list()

while (p * p <= n):

if (pr[p] == True):

for i in range(p * p, n + 1, p):

pr[i] = False

#end-for

#end-if

p += 1

#end-while

cdef int k

for k in range(2,n):

if pr[k]:

res.append(k)

#end-if

#end-for

return res

#end-def

#这是Python动态类型的list

primers=[]

primers=sieveOfEratosthenes(9)

print(primers)

print("调用append方法")

primers.append(11)

print(primers)

程序输出

Cython编译器将生成可处理任何Python对象的代码,并在运行时测试primers是否为列表。如果不是,只要它具有带参数的append方法,该代码就会运行。在后台,生成的代码首先在primers对象上查找append属性(使用PyObject_GetAttr),然后使用完全通用的PyObject_Call Python / C API函数调用该方法。 这实质上模拟了当运行等效的Python字节码时Python解释器将执行的操作。

假设上面的代码中primers变量我们使用静态声明

cdef list primers

现在,Cython可以生成专门的代码,这些代码可以直接从C API调用PyList_SET_ITEM或PyList_Append函数。 这就是上一示例中的PyObject_Call最终仍然要调用的内容,但是静态类型允许Cython绕过了Python解释器在动态调度(Dynamic Dispatch)一系列繁琐沉重的类型检测(内部类型指针查找),这也是Cython的静态版本list比Python动态版本list性能高效的原因。

关于Python解释器的动态调度的详细介绍,请查看此文《第2篇:Cython VS Python 执行原理》

Cython当前支持的集中内置可静态声明的Python类型,我们常用静态声明的可能就是list,dict

type,object

bool

complex

basestring,str,unicode,bytes,bytearray

list,tuple,dict,set,frosenset

array

slace

date,time,datetime,timedelta,tzinfo

上面的列出的中不包括直接C对应的Python类型(例如int,long和float)。 事实证明,在Cython中静态声明和使用PyIntObjects,PyLongObjects或PyFloatObjects并不容易。 幸运的是,这样做的需要很少。 我们只声明常规的C基本数据类型int,long,float和double,然后让Cython为我们进行往返于Python的自动转换。

数字字面量的基本运算

当我们对数字字面量进行加,减或乘运算时,当操作数是动态类型化的Python对象时,这些操作具有Python语义(包括对于数值大的自动Python long强制转换)。当操作数是静态类型的C变量时,它们具有C语义(即,对于有限精度的整数类型,结果可能会溢出)

除数和模数(即计算余数)值得特别提及。使用带符号整数操作数计算模数时,C和Python具有明显不同的行为:C舍入为零,而Python舍入为无穷。例如,使用Python语义时,-1%5的结果为4;但是,如果使用C语义,它将得出-1。当将两个整数相除时,Python始终检查分母,并在其为零时引发ZeroDivisionError,而C没有适当的保护措施。

对于除法/取模运算中,即便指定了C类型的静态数字变量,Cython的行为是倾向于Python的,要获取与C/C++完全相同的语义,我们可以在全局模块级别或在指令注释中使用cdivision编译器指令,如下示例所示

在Python 3中,在C级别,所有整数都是PyLongObjects。Cython以与语言无关的方式在C整数类型和这些Python整数类型之间正确转换,并在无法进行转换时引发OverflowError。

当我们在Cython中使用Python对象时,无论是静态声明还是动态声明,Cython仍将为我们管理对象的所有方面,包括繁琐的引用计数。下一篇我们将会谈到Cython中的引用计数和静态的字符串类型。

python不支持的数据类型有achar bint cfloat dlist_第1篇:Cython的数据类型(第二部分)相关推荐

  1. python不支持的数据类型有achar bint cfloat dlist_python不支持的数据类型有achar bint cfloat dlist_DM 类数据类型...

    类类型 DM7通过类类型在DMSQL程序中实现面向对象编程的支持.类将结构化的数据及对其进行操作的过程或函数封装在一起.允许用户根据现实世界的对象建模,而不必再将其抽象成关系数据. DM7的类类型分为 ...

  2. python不支持以下哪种数据类型_Python 不支持以下哪种数据类型?

    Python 不支持以下哪种数据类型? 答:char 中国大学MOOC: 为了充分利用学习时间,下列方法可行的是: 答:尽量选择理想的固定场所学习\n充分利用等候和其它碎片时间\n把握一天中的最佳状态 ...

  3. 下列数据类型中python不支持的是_ 下列选项中 ,Python 不支持的数据类型有 ( ) 。_学小易找答案...

    [单选题] 下列标识符中 , 合法的是 ( ) . [简答题]说明轴承代号7204AC表达的含义. [判断题]type() 函数可以查看变量的数据类型. ( ) [名词解释]限界 [单选题]体育教学 ...

  4. 在下列数据类型中、python不支持的是_在下列数据类型中, Python不支持的是_学小易找答案...

    [填空题]如果想测试变量的类型,可以使用 __________关键字 来实现. [单选题]如在类中存在有_value,则表示它是 [填空题]当运行测试输入6789时,写出下面 Python程序的执行结 ...

  5. python不支持单字符类型_Python数据类型之字符串

    1. Python字符串的创建 字符串是Python中最常见的数据类型,通常使用单引号或双引号来定义一个字符串,如下: str = "我是字符串" str1 = '我也是字符串' ...

  6. 哪种类型是python不支持的_Python不支持以下哪种数据类型?

    Python不支持以下哪种数据类型? <水上音乐>是作曲家()创作的器乐作品.A:斯卡拉蒂B:维瓦尔第C:亨德尔 瘀血阻络证胁痛代表方是血府逐瘀汤.A:错B:对 不论是独立式按键还是矩阵式 ...

  7. python不支持切片的数据类型,python必须知道的六种数据类型

    哈喽,大家好呀 今天让我们来学习学习python3中六大必不可少的标准数据类型 1.数字类型 数字类型(Number)简单理解的就是数值,在python语句中我们不缺乏要写数字和数值,给一个变量或者多 ...

  8. python不支持哪种数据类型_Python不支持以下哪种数据类型?

    Python不支持以下哪种数据类型? 生命的意义在于在工作中实现自我价值,而不是一个关于做了什么事和得到多少报酬的问题.A:错B:对 我们撰写发明专利申请书时可以将自己的发明创造的核心材料以论文形式进 ...

  9. python不支持以下哪种数据类型_下列数据类型中, Python不支持的是()。_学小易找答案...

    [判断题]a={},type(a)结果是 . (5.0分) [简答题]内造型设计 [填空题]水分子之间存在着质子的传递作用,称为水的 作用,这个作用的平衡常数在25度时等于 . [填空题]len('3 ...

最新文章

  1. 8 list切片_P018 python基础:数据类型之列表切片02
  2. 【hdu3555】Bomb 数位dp
  3. LiveVideoStackCon深圳-发掘移动客户端更多可能
  4. Windows环境下文件的彻底删除与恢复,推荐几个工具(整理)
  5. python字符串_教你快速了解 Python 字符串
  6. html语言可以干什么,JavaScript语言能做什么?
  7. 为什么栈的数组长度必须是一个常量?而堆的数组长度可以是变量。为什么栈的大小有限制?
  8. Flutter实战一Flutter聊天应用(五)
  9. android onscrolllistener判断到底部,android中RecycleView添加下滑到底部的监听示例
  10. 人类赋予人工智能伦理,生物进化方向的突破是关键【刘锋博士南科大发言】
  11. C++特性:封装、继承、多态
  12. 浏览器访问linux终端,使用浏览器访问 Linux 终端
  13. 一款用来下载pdf word zip img各种文件的js插件
  14. 单片机编程软件很简单(19),keil单片机编程软件3点介绍
  15. ThinkpadX220 windows10 博通bcm94352hmb的蓝牙连接音箱播放声音断断续续的解决方案
  16. idea卸载不干净怎么办_卸载删除面具(Magisk)后,手机不开机怎么办
  17. 机器人油封_机器人油封 机器人减速机 机器人伺服电机油封 KVNOK油封
  18. C#学习 - 关于Single()
  19. Python实现爬取下载百度图片
  20. Cisco交换机密码修复

热门文章

  1. java打印直角三角形和倒立直角三角形
  2. exif linux php扩展_LNMP环境为PHP添加exif扩展
  3. linux文件赋予755权限,Linux文件和目录的777、755、644权限解释
  4. Java查询图书信息
  5. IDEA 配置Tomcat
  6. vue 拖动 datatransfer 问题_electron-vue跨平台桌面应用开发实战教程(四)——窗口样式amp;打开新窗口...
  7. java concurrent int_java.util.concurrent.AtomicInteger
  8. MXNet的Model API
  9. java 下载后删除,在服务器端生成文件后,下载后并删除,改了后发现文件变成空白解决思路...
  10. cmd运行python程序