1. 程式人生 > >百度T7架構師透析Python物件你需要知道這些

百度T7架構師透析Python物件你需要知道這些

1. Python物件

Python使用物件模型來儲存資料。構造任何型別的值都是一個物件。


所有的Python物件都擁有三個特性:身份,型別和值。

身份:

每一個物件都有一個唯一的身份標識自己,任何物件的身份可以使用內建函式 id() 來得到。這個值可以被認為是該物件的記憶體地址。您極少會用到這個值,也不用關心它究竟是什麼。

型別:

物件的型別決定了該物件可以儲存什麼型別的值,可以進行什麼樣的操作,以及遵循什麼樣的規則。你可以用內建函式 type() 來檢視Python物件的型別。因為在Python中型別也是物件,所以 type() 返回的是物件而不是簡單的字串。

值:

物件表示的資料項

上面三個特性在物件建立的時候就被賦值,除了值之外,其他兩個特性都是隻讀的。

如果物件支援更新操作,那麼它的值就可以改變,否則也是隻讀的。物件的值是否可更改被稱為物件的可改變性(mutability),只要一個還沒有被銷燬,這些特性就一直存在。

Python有一系列的基本(內建)資料型別,絕大多數應用程式通常使用標準型別,對特定的資料儲存則通過建立和例項化類來實現。

1.1 物件屬性

某些Python物件有屬性、值或相關聯的可執行程式碼,比如方法。Python用點( . )標記法來訪問屬性。屬性包括相應物件的名字等等。最常用的屬性是函式和方法,不過有一些Python型別也有資料屬性。含有資料屬性的物件包括(但不僅限於):類、類例項、模組、複數和檔案。

 

2. 標準型別

數字(分為幾個子型別,其中有三個是整型)

整型

長整型

浮點型

複數型

布林型

字串

列表

元祖

字典

3. 其他內建型別

型別

Null物件(None)

檔案

集合/固定集合

函式/方法

模組

3.1 型別物件和type型別物件

物件的一系列固有行為和特性(比如支援哪些運算,具 有哪些方法)必須事先定義好。從這個角度看,雖然看上去把型別本身也當成物件有點特別,但型別正是儲存這些資訊的最佳位置。描述一種 型別所需要的資訊不可能用一個字串來搞定,所以型別不能是一個簡單的字串,這些資訊 不能也不應該和資料儲存在一起, 所以我們將型別定義成物件。


>>> type(12)

<type 'int'>

>>> type(type(12))

<type 'type'>

沒錯,所有型別物件的型別都是 type。

3.2 None,Python的Null物件

Python有一個特殊的型別,被稱作Null物件或者NoneType,它只有一個值,那就是None。他不支援任何運算也沒有任何內建方法。

None沒有什麼有用的屬性,它的布林值總是False。

布林值

所有的標準物件均可用於布林測試,同類型的物件之間可以比較大小。每個物件天生具有布林 True 或 False 值。空物件、值為零的任何數字或者Null 物件 None的布林值都是False。

下列物件的布林值是False。

None

False

所有值為零的數

空字串

空列表

空元組

空字典


4. 內部型別 

程式碼

跟蹤記錄

切片

省略

Xrange

一般的程式設計師通常不會直接和這些物件打交道。

4.1 程式碼物件

程式碼物件是編譯過的Python原始碼片段,它是可執行物件。通過呼叫內建函式compile() 可以得到程式碼物件。程式碼物件可以被exec命令或eval() 內建函式來執行。

程式碼物件本身不包含任何執行環境資訊,它是使用者自定義函式的核心,在被執行時動態獲得上下文。一個函式除了有程式碼物件屬性以外,還有一些其他函式必須的屬性,包括函式名,文件字串,預設引數,及全域性名稱空間等等。

4.2 幀物件

幀物件表示Python的執行棧幀。幀物件包含Python直譯器在執行時所需要知道的所有資訊。它的屬性包括指向上一幀的連結,正在被執行的程式碼物件,本地及全域性名字空間字典以及當前指令等。每次函式呼叫產生一個新的幀,每一個幀物件都會相應建立一個C棧幀。用到幀物件的一個地方是跟蹤記錄物件。

4.3 跟蹤記錄物件

當你的程式碼出錯時,Python就會引發一個異常。如果異常未被捕獲和處理,直譯器就會退出指令碼執行,並顯示診斷資訊。當異常發生時,一個包含針對異常的棧跟蹤資訊的跟蹤記錄物件被建立。如果一個異常有自己的處理程式,處理程式就可以訪問這個跟蹤記錄物件。

4.4 切片物件

當使用Python擴充套件的切片語法時,就會建立切片物件。擴充套件的切片語法允許對不同的索引切片操作,切片物件也可以由內建函式slice() 來生成。步進切片允許利用第三個切片元素進行步進切片,它的語法是sequence[起始索引 :結束索引:步進值]。

4.5 省略物件

省略物件用於擴充套件切片語法中,起記號作用。 這個物件在切片語法中表示省略號。類似Null 物件 None, 省略物件有一個唯一的名字 Ellipsis, 它的布林值始終為 True。

4.6 XRange 物件

         呼叫內建函式 xrange() 會生成一個 Xrange 物件,xrange()是內建函式 range()的兄弟版本, 用於需要節省記憶體使用或 range()無法完成的超大資料集場合。


5. 標準型別運算子

5.1 物件值的比較

比較運算子用來判斷同類型物件是否相等,所有的內建型別均支援比較運算,比較運算返 回布林值 True 或 False。

<

>

<=

>=

==

!=

5.2 物件身份比較

作為對值比較的補充,Python 也支援物件本身的比較。物件可以被賦值到另一個變數(通 過引用)。因為每個變數都指向同一個(共享的)資料物件,只要任何一個引用發生改變,該物件的其它引用也會隨之改變。

a is b

這個表示式等價於下面的表示式 id(a) == id(b)

>>> a = [ 5, 'hat', -9.3]
>>> b = a
>>> a is b
True
>>> a is not b
False
>>>
>>> b = 2.5e-5
>>> b
2.5e-005
>>> a
[5, 'hat', -9.3]
>>> a is b
False
>>> a is not b
True

在上面的例子中,使用的是浮點數而不是整數。為什麼這樣?整數物件和 字串物件是不可變物件,所以Python會很高效的快取它們。這會造成我們認為Python應該建立新物件時,它卻沒有建立新物件的假象。看下面的例子:

>>> a = 1
>>> id(a)
8402824
>>> b = 1
>>> id(b)
8402824
>>>
>>> c = 1.0
>>> id(c)
8651220
>>> d = 1.0
>>> id(d)
8651204

在上面的例子中,a 和 b 指向了相同的整數物件,但是 c 和 d 並沒有指向相同的浮點數 物件。


Python僅快取簡單整數,因為它認為在Python應用程式中這些小整數會經常被用到。目前Python 快取的整數範圍是(-1,256),不過這個範圍是會改變的。


5.3 布林型別

布林邏輯運算子 and, or 和 not 都是 Python 關鍵字,not 運算子擁有最高優先順序,只比所有比較運算子低一級。 and 和 or 運 算符則相應的再低一級。


>>> x, y = 3.1415926536, -1024
>>> x < 5.0
True
>>> not (x < 5.0) 
False
>>> (x < 5.0) or (y > 2.718281828) 
True
>>> (x < 5.0) and (y > 2.718281828) 
False
>>> not (x is y)
True
6. 標準型別內建函式
6.1 type()
type() 接受一個物件做為引數,並返回它的型別。它的返回值是一個型別物件。
>>> type(4)     # int type
<type 'int'>
>>>
>>> type('Hello World!')
<type 'string'>
# string type
>>>
>>> type(type(4))       # type type
<type 'type'>

6.2 str() 和 repr() (及 `` 運算子)

內建函式 str() 和 repr() 或反引號運算子(``) 可以方便的以字串的方式獲取物件的 內容、型別、數值屬性等資訊。


>>> str(4.53-2j)
'(4.53-2j)'
>>>
>>> str(1)
'1'
>>>
>>> str(2e10)
'20000000000.0'
>>>
>>> str([0, 5, 9, 9])
'[0, 5, 9, 9]'
>>>
>>> repr([0, 5, 9, 9])
'[0, 5, 9, 9]'
>>>
>>> `[0, 5, 9, 9]`
'[0, 5, 9, 9]'

repr() 輸出對 Python 比較友好, 而 str()的輸出對人比較友好。雖然如此, 很多情況下這三者的輸出仍然都是完全一樣的。


6.3  type() 和 isinstance()

type()內建函式可以幫助你確認呼叫的就是你想要的函式或物件。除了內建函式 type(), 還有一個有用的內建函式叫 isinstance().利用它可以確認一 個物件的型別。


7. 型別工廠函式

原來的 所謂內建轉換函式象 int(), type(), list() 等等, 現在都成了工廠函式。 也就是說雖然他 們看上去有點象函式, 實質上他們是類。當你呼叫它們時, 實際上是生成了該型別的一個實 例, 就象工廠生產貨物一樣。

dict()

bool()

set() ,frozenset()

object()

classmethod()

staticmethod()

super()

property()

file()

8. 標準型別的分類

如果讓我們最囉嗦的描述標準型別,我們也許會稱它們是 Python 的“基本內建資料物件原 始型別”。

“基本”,是指這些型別都是Python提供的標準或核心型別。

“內建”,是由於這些型別是Python預設就提供的

“資料”,因為他們用於一般資料儲存

“物件”,因為物件是資料和功能的預設抽象

“原始”,因為這些型別提供的是最底層的粒度資料儲存

“型別”,因為他們就是資料型別

8.1 儲存模型                                                                        

以儲存模型標準的型別分類

分類  Python 型別 標量/原子型別 數值(所有的數值型別),字串(全部是文字) 容器型別 列表、元組、字典

8.2 更新模型

以更新模型為標準的型別分類

分類

Python 型別

可變型別

列表, 字典

不可變型別

數字、字串、元組

>>> x = 'Python numbers and strings'
>>> print id(x)
16191392
>>> x = 'are immutable?!? What gives?'
>>> print id(x)
16191232
>>> i = 0
>>> print id(i)
7749552
>>> i = i + 1
>>> print id(i)

上面的例子中,事實上是一個新物件被建立,然後它取代了舊物件。

新建立的物件被關聯到原來的變數名, 舊物件被丟棄,垃圾回收器會在適當的時機回收這 些物件。你可以通過內建函式 id()來確認物件的身份在兩次賦值前後發生了變化。

>>> aList = ['ammonia', 83, 85, 'lady']
>>> aList
['ammonia', 83, 85, 'lady']
>>>
>>> aList[2]
85
>>>
>>> id(aList)
135443480
>>>
>>> aList[2] = aList[2] + 1
>>> aList[3] = 'stereo'
>>> aList
['ammonia', 83, 86, 'stereo']
>>>
>>> id(aList)
135443480
>>>
>>> aList.append('gaudy')
>>> aList.append(aList[2] + 1)
>>> aList
['ammonia', 83, 86, 'stereo', 'gaudy', 87]
>>>
>>> id(aList)
135443480

注意列表的值不論怎麼改變, 列表的 ID 始終保持不變。

8.3 訪問型別

以訪問模型為標準的型別分類

分類

Python 型別

直接訪問

數字

順序訪問

字串、列表、元組

對映訪問

字典