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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python的底层是c_python基本数据类型底层实现

發(fā)布時(shí)間:2025/3/19 python 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python的底层是c_python基本数据类型底层实现 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、前言

我們知道,python是一種動態(tài)語言,可以將任何類型的數(shù)據(jù)賦給任何變量,譬如:

#Python代碼

x = 4x= "four"

這里已經(jīng)將 x 變量的內(nèi)容由整型轉(zhuǎn)變成了字符串,而同樣的操作在 C 語言中將會導(dǎo)致(取決于編譯器設(shè)置)編譯錯(cuò)誤或其他未知的后果。

這種靈活性是使 Python 和其他動態(tài)類型的語言更易用的原因之一。理解這一特性如何工作是學(xué)習(xí)用 Python 有效且高效地分析數(shù)據(jù)的重要因素。但是這種類型靈活性也指出了一個(gè)事實(shí):

Python 變量不僅是它們的值,還包括了關(guān)于值的類型的一些額外信息。

二、整型

標(biāo)準(zhǔn)的 Python 實(shí)現(xiàn)是用 C 語言編寫的。這意味著每一個(gè) Python 對象都是一個(gè)偽 C 語言結(jié)構(gòu)體,該結(jié)構(gòu)體不僅包含其值,還有其他信息。例如,當(dāng)我們在 Python 中定義一個(gè)整型,例如 x = 10000 時(shí),x 并不是一個(gè)“原生”整型,而是一個(gè)指針,指向一個(gè) C 語言的復(fù)合結(jié)構(gòu)體,結(jié)構(gòu)體里包含了一些值。查看 Python 3.4 的源代碼,可以發(fā)現(xiàn)整型(長整型)的定義,如下所示(C 語言的宏經(jīng)過擴(kuò)展之后):

struct_longobject {longob_refcnt;

PyTypeObject*ob_type;

size_t ob_size;long ob_digit[1];

};

Python 3.4 中的一個(gè)整型實(shí)際上包括 4 個(gè)部分。

ob_refcnt 是一個(gè)引用計(jì)數(shù),它幫助 Python 默默地處理內(nèi)存的分配和回收。

ob_type 將變量的類型編碼。

ob_size 指定接下來的數(shù)據(jù)成員的大小。

ob_digit 包含我們希望 Python 變量表示的實(shí)際整型值。

這意味著與 C 語言這樣的編譯語言中的整型相比,在 Python 中存儲一個(gè)整型會有一些開銷,正如下圖所示:

這里 PyObject_HEAD 是結(jié)構(gòu)體中包含引用計(jì)數(shù)、類型編碼和其他之前提到的內(nèi)容的部分。

兩者的差異在于,C 語言整型本質(zhì)上是對應(yīng)某個(gè)內(nèi)存位置的標(biāo)簽,里面存儲的字節(jié)會編碼成整型。而 Python 的整型其實(shí)是一個(gè)指針,指向包含這個(gè) Python 對象所有信息的某個(gè)內(nèi)存位置,其中包括可以轉(zhuǎn)換成整型的字節(jié)。由于 Python 的整型結(jié)構(gòu)體里面還包含了大量額外的信息,所以 Python 可以自由、動態(tài)地編碼。但是,Python 類型中的這些額外信息也會成為負(fù)擔(dān),在多個(gè)對象組合的結(jié)構(gòu)體中尤其明顯。

三、列表

設(shè)想如果使用一個(gè)包含很多 Python 對象的 Python 數(shù)據(jù)結(jié)構(gòu),會發(fā)生什么? Python 中的標(biāo)準(zhǔn)可變多元素容器是列表。可以用如下方式創(chuàng)建一個(gè)整型值列表:

In[1]: L = list(range(10))

L

Out[1]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In[2]: type(L[0])

Out[2]: int

或者創(chuàng)建一個(gè)字符串列表:

In[3]: L2 = [str(c) for c inL]

L2

Out[3]: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

In[4]: type(L2[0])

Out[4]: str

因?yàn)?Python 的動態(tài)類型特性,甚至可以創(chuàng)建一個(gè)異構(gòu)的列表:

In[5]: L3 = [True, "2", 3.0, 4]

[type(item)for item inL3]

Out[5]: [bool, str, float, int]

但是想擁有這種靈活性也是要付出一定代價(jià)的:為了獲得這些靈活的類型,列表中的每一項(xiàng)必須包含各自的類型信息、引用計(jì)數(shù)和其他信息;也就是說,每一項(xiàng)都是一個(gè)完整的 Python 對象。來看一個(gè)特殊的例子,如果列表中的所有變量都是同一類型的,那么很多信息都會顯得多余——將數(shù)據(jù)存儲在固定類型的數(shù)組中應(yīng)該會更高效。動態(tài)類型的列表和固定類型的(NumPy 式)數(shù)組間的區(qū)別如下圖所示。

在實(shí)現(xiàn)層面,數(shù)組基本上包含一個(gè)指向連續(xù)數(shù)據(jù)塊的指針。另一方面,Python 列表包含一個(gè)指向指針塊的指針,這其中的每一個(gè)指針對應(yīng)一個(gè)完整的 Python 對象(如前面看到的 Python 整型)。另外,列表的優(yōu)勢是靈活,因?yàn)槊總€(gè)列表元素是一個(gè)包含數(shù)據(jù)和類型信息的完整結(jié)構(gòu)體,而且列表可以用任意類型的數(shù)據(jù)填充。固定類型的 NumPy 式數(shù)組缺乏這種靈活性,但是能更有效地存儲和操作數(shù)據(jù)。

四、固定類型數(shù)組

1. 使用array模塊創(chuàng)建數(shù)組

Python 提供了幾種將數(shù)據(jù)存儲在有效的、固定類型的數(shù)據(jù)緩存中的選項(xiàng)。內(nèi)置的數(shù)組(array)模塊(在 Python 3.3 之后可用)可以用于創(chuàng)建統(tǒng)一類型的密集數(shù)組:

In[6]: importarray

L= list(range(10))

A= array.array('i', L)

A

Out[6]: array('i', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

這里的 'i' 是一個(gè)數(shù)據(jù)類型碼,表示數(shù)據(jù)為整型。

更實(shí)用的是 NumPy 包中的 ndarray 對象。Python 的數(shù)組對象提供了數(shù)組型數(shù)據(jù)的有效存儲,而 NumPy 為該數(shù)據(jù)加上了高效的操作。稍后將介紹這些操作,這里先展示幾種創(chuàng)建 NumPy 數(shù)組的方法。

從用 np 別名導(dǎo)入 NumPy 的標(biāo)準(zhǔn)做法開始:

In[7]: import numpy as np

2. 從python列表創(chuàng)建NumPy 數(shù)組

首先,可以用 np.array 從 Python 列表創(chuàng)建數(shù)組:

In[8]: #整型數(shù)組:

np.array([1, 4, 2, 5, 3])

Out[8]: array([1, 4, 2, 5, 3])

請記住,不同于 Python 列表,NumPy 要求數(shù)組必須包含同一類型的數(shù)據(jù)。如果類型不匹配,NumPy 將會向上轉(zhuǎn)換(如果可行)。這里整型被轉(zhuǎn)換為浮點(diǎn)型:

In[9]: np.array([3.14, 4, 2, 3])

Out[9]: array([ 3.14, 4. , 2. , 3. ])

如果希望明確設(shè)置數(shù)組的數(shù)據(jù)類型,可以用 dtype 關(guān)鍵字:

In[10]: np.array([1, 2, 3, 4], dtype='float32')

Out[10]: array([ 1., 2., 3., 4.], dtype=float32)

最后,不同于 Python 列表,NumPy 數(shù)組可以被指定為多維的。以下是用列表的列表初始化多維數(shù)組的一種方法:

In[11]: #嵌套列表構(gòu)成的多維數(shù)組

np.array([range(i, i + 3) for i in [2, 4, 6]])

Out[11]: array([[2, 3, 4],

[4, 5, 6],

[6, 7, 8]])

內(nèi)層的列表被當(dāng)作二維數(shù)組的行。

3. 從頭創(chuàng)建NumPy 數(shù)組

面對大型數(shù)組的時(shí)候,用 NumPy 內(nèi)置的方法從頭創(chuàng)建數(shù)組是一種更高效的方法。以下是幾個(gè)示例:

In[12]: #創(chuàng)建一個(gè)長度為10的數(shù)組,數(shù)組的值都是0

np.zeros(10, dtype=int)

Out[12]: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

In[13]: #創(chuàng)建一個(gè)3×5的浮點(diǎn)型數(shù)組,數(shù)組的值都是1

np.ones((3, 5), dtype=float)

Out[13]: array([[ 1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.],

[1., 1., 1., 1., 1.]])

In[14]: #創(chuàng)建一個(gè)3×5的浮點(diǎn)型數(shù)組,數(shù)組的值都是3.14

np.full((3, 5), 3.14)

Out[14]: array([[ 3.14, 3.14, 3.14, 3.14, 3.14],

[3.14, 3.14, 3.14, 3.14, 3.14],

[3.14, 3.14, 3.14, 3.14, 3.14]])

In[15]: #創(chuàng)建一個(gè)3×5的浮點(diǎn)型數(shù)組,數(shù)組的值是一個(gè)線性序列

#從0開始,到20結(jié)束,步長為2

#(它和內(nèi)置的range()函數(shù)類似)

np.arange(0, 20, 2)

Out[15]: array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])

In[16]: #創(chuàng)建一個(gè)5個(gè)元素的數(shù)組,這5個(gè)數(shù)均勻地分配到0~1

np.linspace(0, 1, 5)

Out[16]: array([ 0. , 0.25, 0.5 , 0.75, 1. ])

In[17]: #創(chuàng)建一個(gè)3×3的、在0~1均勻分布的隨機(jī)數(shù)組成的數(shù)組

np.random.random((3, 3))

Out[17]: array([[ 0.99844933, 0.52183819, 0.22421193],

[0.08007488, 0.45429293, 0.20941444],

[0.14360941, 0.96910973, 0.946117]])

In[18]: #創(chuàng)建一個(gè)3×3的、均值為0、方差為1的

#正態(tài)分布的隨機(jī)數(shù)數(shù)組

np.random.normal(0, 1, (3, 3))

Out[18]: array([[ 1.51772646, 0.39614948, -0.10634696],

[0.25671348, 0.00732722, 0.37783601],

[0.68446945, 0.15926039, -0.70744073]])

In[19]: #創(chuàng)建一個(gè)3×3的、[0, 10)區(qū)間的隨機(jī)整型數(shù)組

np.random.randint(0, 10, (3, 3))

Out[19]: array([[2, 3, 4],

[5, 7, 8],

[0,5, 0]])

In[20]: #創(chuàng)建一個(gè)3×3的單位矩陣

np.eye(3)

Out[20]: array([[ 1., 0., 0.],

[ 0.,1., 0.],

[ 0., 0.,1.]])

In[21]: #創(chuàng)建一個(gè)由3個(gè)整型數(shù)組成的未初始化的數(shù)組

#數(shù)組的值是內(nèi)存空間中的任意值

np.empty(3)

Out[21]: array([ 1., 1., 1.])

五、NumPy標(biāo)準(zhǔn)數(shù)據(jù)類型

NumPy 數(shù)組包含同一類型的值,因此詳細(xì)了解這些數(shù)據(jù)類型及其限制是非常重要的。因?yàn)?NumPy 是在 C 語言的基礎(chǔ)上開發(fā)的,所以 C、Fortran 和其他類似語言的用戶會比較熟悉這些數(shù)據(jù)類型。

數(shù)據(jù)類型

描述

bool_

布爾值(真、True 或假、False),用一個(gè)字節(jié)存儲

int_

默認(rèn)整型(類似于 C 語言中的 long,通常情況下是 int64 或 int32)

intc

同 C 語言的 int 相同(通常是 int32 或 int64)

intp

用作索引的整型(和 C 語言的 ssize_t 相同,通常情況下是 int32 或 int64)

int8

字節(jié)(byte,范圍從–128 到 127)

int16

整型(范圍從–32768 到 32767)

int32

整型(范圍從–2147483648 到 2147483647)

int64

整型(范圍從–9223372036854775808 到 9223372036854775807)

uint8

無符號整型(范圍從 0 到 255)

uint16

無符號整型(范圍從 0 到 65535)

uint32

無符號整型(范圍從 0 到 4294967295)

uint64

無符號整型(范圍從 0 到 18446744073709551615)

float_

float64 的簡化形式

float16

半精度浮點(diǎn)型:符號比特位,5 比特位指數(shù)(exponent),10 比特位尾數(shù)(mantissa)

float32

單精度浮點(diǎn)型:符號比特位,8 比特位指數(shù),23 比特位尾數(shù)

float64

雙精度浮點(diǎn)型:符號比特位,11 比特位指數(shù),52 比特位尾數(shù)

complex_

complex128 的簡化形式

complex64

復(fù)數(shù),由兩個(gè) 32 位浮點(diǎn)數(shù)表示

complex128

復(fù)數(shù),由兩個(gè) 64 位浮點(diǎn)數(shù)表示

上表列出了標(biāo)準(zhǔn) NumPy 數(shù)據(jù)類型。請注意,當(dāng)構(gòu)建一個(gè)數(shù)組時(shí),你可以用一個(gè)字符串參數(shù)來指定數(shù)據(jù)類型:

np.zeros(10, dtype='int16')

或者用相關(guān)的 NumPy 對象來指定:

np.zeros(10, dtype=np.int16)

還可以進(jìn)行更高級的數(shù)據(jù)類型指定,例如指定高位字節(jié)數(shù)或低位字節(jié)數(shù);更多的信息可以在 NumPy 文檔(http://numpy.org/)中查看。

六、參考

1. 《Python數(shù)據(jù)科學(xué)手冊》 [美] Jake VanderPlas [VanderPlas, Jake]

(完)

總結(jié)

以上是生活随笔為你收集整理的python的底层是c_python基本数据类型底层实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。