日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

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

發布時間:2025/3/15 python 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python不支持的数据类型有achar bint cfloat dlist_第1篇:Cython的数据类型(第二部分) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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的数据类型(第二部分)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。