Skip to content

值得您信賴的旅遊品牌 | 團體旅遊、自由行的專家‎

機場接送

Menu
  • 首頁
  • 旅遊天地
  • 裝潢設計
  • 環保清潔
  • 發燒車訊
Menu

【Python源碼剖析】對象模型概述

Posted on 2021-03-172021-03-17 by admin

目錄

  • 一切皆對象
  • 類型、對象體系
  • 變量只是名字
  • 可變對象 與 不可變對象
  • 定長對象 與 變長對象
  • 更多章節
  • 附錄

Python 是一門 面向對象 語言,實現了一個完整的面向對象體系,簡潔而優雅。

與其他面向對象編程語言相比, Python 有自己獨特的一面。 這讓很多開發人員在學習 Python 時,多少有些無所適從。 那麼,Python 對象模型都有哪些特色呢?

一切皆對象

首先,在 Python 世界, 基本類型也是對象 ,與通常意義的“對象”形成一個有機統一。 換句話講, Python 不再區別對待基本類型和對象,所有基本類型內部均由對象實現。 一個整數是一個對象,一個字符串也是一個對象:

>>> a = 1
>>> b = 'abc'

其次, Python 中的 類型也是一種對象 ,稱為 類型對象 。 整數類型是一個對象,字符串類型是一個對象,程序中通過 class 關鍵字定義的類也是一個對象。

舉個例子,整數類型在 Python 內部是一個對象,稱為 類型對象 :

>>> int
<class 'int'>

通過整數類型 實例化 可以得到一個整數對象,稱為 實例對象 :

>>> int('1024')
1024

面向對象理論中的“ 類 ”和“ 對象 ”這兩個基本概念,在 Python 內部都是通過對象實現的,這是 Python 最大的特點。

類型、對象體系

a 是一個整數對象( 實例對象 ),其類型是整數類型( 類型對象 ):

>>> a = 1
>>> type(a)
<class 'int'>
>>> isinstance(a, int)
True

那麼整數類型的類型又是什麼呢?

>>> type(int)
<class 'type'>

可以看到,整數類型的類型還是一種類型,即 類型的類型 。 只是這個類型比較特殊,它的實例對象還是類型對象。

Python 中還有一個特殊類型 object ,所有其他類型均繼承於 object ,換句話講 object 是所有類型的基類:

>>> issubclass(int, object)
True

綜合以上關係,得到以下關係圖:

內置類型已經搞清楚了,自定義類型及對象關係又如何呢?定義一個簡單的類來實驗:

class Dog(object):

    def yelp(self):
        print('woof')

創建一個 Dog 實例,毫無疑問,其類型是 Dog :

>>> dog = Dog()
>>> dog.yelp()
woof
>>> type(dog)
<class '__main__.Dog'>

Dog 類的類型自然也是 type ,其基類是 object (就算不顯式繼承也是如此):

>>> type(Dog)
<class 'type'>
>>> issubclass(Dog, object)
True

自定義子類及實例對象在圖中又處於什麼位置?定義一個獵犬類進行實驗:

class Sleuth(Dog):

    def hunt(self):
        pass

可以看到, 獵犬對象( sleuth )是獵犬類( Sleuth )的實例, Sleuth 的類型同樣是 type :

>>> sleuth = Sleuth()
>>> sleuth.hunt()
>>> type(sleuth)
<class '__main__.Sleuth'>
>>> type(Sleuth)
<class 'type'>

同時, Sleuth 類繼承自 Dog 類,是 Dog 的子類,當然也是 object 的子類:

>>> issubclass(Sleuth, Dog)
True
>>> issubclass(Sleuth, object)
True

現在不可避免需要討論 type 以及 object 這兩個特殊的類型。

理論上, object 是所有類型的 基類 ,本質上是一種類型,因此其類型必然是 type 。 而 type 是所有類型的類型,本質上也是一種類型,因此其類型必須是它自己!

>>> type(object)
<class 'type'>
>>> type(object) is type
True

>>> type(type)
<class 'type'>
>>> type(type) is type
True

另外,由於 object 是所有類型的 基類 ,理論上也是 type 的基類( __base__ 屬性):

>>> issubclass(type, object)
True
>>> type.__base__
<class 'object'>

但是 object 自身便不能有基類了。為什麼呢? 對於存在繼承關係的類,成員屬性和成員方法查找需要回溯繼承鏈,不斷查找基類。 因此,繼承鏈必須有一個終點,不然就死循環了。

這就完整了!

可以看到,所有類型的基類收斂於 object ,所有類型的類型都是 type ,包括它自己! 這就是 Python 類型、對象體系全圖,設計簡潔、優雅、嚴謹。

該圖將成為後續閱讀源碼、探索 Python 對象模型的有力工具,像地圖一樣指明方向。 圖中所有實體在 Python 內部均以對象形式存在,至於對象到底長啥樣,相互關係如何描述,這些問題先按下不表,後續一起到源碼中探尋答案。

變量只是名字

先看一個例子,定義一個變量 a ,並通過 id 內建函數取出其“地址”:

>>> a = 1
>>> id(a)
4302704784

定義另一個變量 b ,以 a 賦值,並取出 b 的“地址”:

>>> b = a
>>> id(b)
4302704784

驚奇地看到, a 和 b 這兩個變量的地址居然是相同的!這不合常理呀!

對於大多數語言( C 語言為例),定義變量 a 即為其分配內存並存儲變量值:

變量 b 內存空間與 a 獨立,賦值時進行拷貝:

在 Python 中,一切皆對象,整數也是如此, 變量只是一個與對象關聯的名字 :

而變量賦值,只是將當前對象與另一個名字進行關聯,背後的對象是同一個:

因此,在 Python 內部,變量只是一個名字,保存指向實際對象的指針,進而與其綁定。 變量賦值只拷貝指針,並不拷貝指針背後的對象。

可變對象 與 不可變對象

定義一個整數變量:

>>> a = 1
>>> id(a)
4302704784

然後,對其自增 1 :

>>> a += 1
>>> a
2
>>> id(a)
4302704816

數值符合預期,但是對象變了!初學者一臉懵逼,這是什麼鬼?

一切要從 可變對象 和 不可變對象 說起。 可變對象 在對象創建后,其值可以進行修改; 而 不可變對象 在對象創建后的整個生命周期,其值都不可修改。

在 Python 中,整數類型是不可變類型, 整數對象是不可變對象。 修改整數對象時, Python 將以新數值創建一個新對象,變量名與新對象進行綁定; 舊對象如無其他引用,將被釋放。

每次修改整數對象都要創建新對象、回收舊對象,效率不是很低嗎? 確實是。 後續章節將從源碼角度來解答: Python 如何通過 小整數池 等手段進行優化。

可變對象是指創建后可以修改的對象,典型的例子是 列表 ( list ):

>>> l = [1, 2]
>>> l
[1, 2]
>>> id(l)
4385900424

往列表裡頭追加數據,發現列表對象還是原來那個,只不過多了一個元素了:

>>> l.append(3)
>>> l
[1, 2, 3]
>>> id(l)
4385900424

實際上,列表對象內部維護了一個 動態數組 ,存儲元素對象的指針:

列表對象增減元素,需要修改該數組。例如,追加元素 3 :

定長對象 與 變長對象

Python 一個對象多大呢?相同類型對象大小是否相同呢? 想回答類似的問題,需要考察影響對象大小的因素。

標準庫 sys 模塊提供了一個查看對象大小的函數 getsizeof :

>>> import sys
>>> sys.getsizeof(1)
28

先觀察整數對象:

>>> sys.getsizeof(1)
28
>>> sys.getsizeof(100000000000000000)
32
>>> sys.getsizeof(100000000000000000000000000000000000000000000)
44

可見整數對象的大小跟其數值有關,像這樣 大小不固定 的對象稱為 變長對象 。

我們知道,位數固定的整數能夠表示的數值範圍是有限的,可能導致 溢出 。 Python 為解決這個問題,採用類似 C++ 中 大整數類 的思路實現整數對象 —— 串聯多個普通 32 位整數,以便支持更大的數值範圍。 至於需要多少個 32 位整數,則視具體數值而定,數值不大的一個足矣,避免浪費。

這樣一來,整數對象需要在頭部額外存儲一些信息,記錄對象用了多少個 32 位整數。 這就是變長對象典型的結構,先有個大概印象即可,後續講解整數對象源碼時再展開。

接着觀察字符串對象:

>>> sys.getsizeof('a')
50
>>> sys.getsizeof('abc')
52

字符串對象也是變長對象,這個行為非常好理解,畢竟字符串長度不盡相同嘛。 此外,注意到字符串對象大小比字符串本身大,因為對象同樣需要維護一些額外的信息。 至於具體需要維護哪些信息,同樣留到源碼剖析環節中詳細介紹。

那麼,有啥對象是定長的呢?—— 浮點數對象 float :

>>> sys.getsizeof(1.)
24
>>> sys.getsizeof(1000000000000000000000000000000000.)
24

浮點數背後是由一個 double 實現,就算表示很大的數,浮點數對象的大小也不變。

為啥 64 位的 double 可以表示這麼大的範圍呢?答案是:犧牲了精度。

>>> int(1000000000000000000000000000000000.)
999999999999999945575230987042816

由於浮點數存儲位數是固定的,它能表示的數值範圍也是有限的,超出便會拋錨:

>>> 10. ** 1000
Traceback (most recent call last):
	File "<stdin>", line 1, in <module>
OverflowError: (34, 'Result too large')

更多章節

洞悉 Python 虛擬機運行機制,探索高效程序設計之道!

到底如何才能提升我的 Python 開發水平,向更高一級的崗位邁進? 如果你有這些問題或者疑惑,請訂閱我們的專欄,閱讀更多章節:

  • 內建對象
  • 虛擬機
  • 函數機制
  • 類機制
  • 生成器與協程
  • 內存管理機制

附錄

更多 Python 技術文章請訪問:小菜學Python,轉至 原文 可獲得最佳閱讀體驗。

訂閱更新,獲取更多學習資料,請關注 小菜學編程 :

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

※網頁設計最專業,超強功能平台可客製化

※別再煩惱如何寫文案,掌握八大原則!

好站推薦

  • 健康醫療 減重知識專區
  • 婚紗世界 婚紗攝影寫真網
  • 成人話題 未滿18請勿進入
  • 流行時尚 時下流行愛美情報
  • 理財資訊 當舖借貸信用卡各式理財方法
  • 生活情報 各行各業情報資訊
  • 科技資訊 工業電子3C產品
  • 網路資訊 新奇趣味爆笑內容
  • 美食分享 全台各式名產 伴手禮
  • 裝潢設計 買屋賣屋裝修一羅框
  • 視覺設計 T恤、團體服、制服、polo衫

近期文章

  • 低配高配相差甚遠 怎樣花最少的錢享受到高配置?_網頁設計公司
  • 數清楚卡里的餘額!一波超帥的SUV還有9天就要登陸我國了_如何寫文案
  • 近期想買車必看 雙11這些車型都有優惠_網頁設計公司
  • 月薪一萬兩萬三四萬,怎麼買BMW 2系旅行車才划算?_網頁設計
  • 中國自主品牌新勢力 比速汽車正式發布_貨運

標籤

USB CONNECTOR  南投搬家公司費用 古典家具推薦 台中室內設計 台中室內設計師 台中搬家 台中搬家公司 台中電動車 台北網頁設計 台東伴手禮 台東名產 地板施工 大圖輸出 如何寫文案 婚禮錄影 宜蘭民宿 家具工廠推薦 家具訂製工廠推薦 家具訂製推薦 實木地板 床墊 復刻家具推薦 新竹婚宴會館 木地板 木質地板 柚木地板 桃園機場接送 桃園自助婚紗 沙發修理 沙發換皮 海島型木地板 潭子電動車 牛軋糖 租車 網站設計 網頁設計 網頁設計公司 貨運 超耐磨木地板 銷售文案 隱形鐵窗 電動車 馬賽克拼貼 馬賽克磁磚 馬賽克磚

彙整

  • 2021 年 4 月
  • 2021 年 3 月
  • 2021 年 2 月
  • 2021 年 1 月
  • 2020 年 12 月
  • 2020 年 11 月
  • 2020 年 10 月
  • 2020 年 9 月
  • 2020 年 8 月
  • 2020 年 7 月
  • 2020 年 6 月
  • 2020 年 5 月
  • 2020 年 4 月
  • 2020 年 3 月
  • 2020 年 2 月
  • 2020 年 1 月
  • 2019 年 12 月
  • 2019 年 11 月
  • 2019 年 10 月
  • 2019 年 9 月
  • 2019 年 8 月
  • 2019 年 7 月
  • 2019 年 6 月
  • 2019 年 5 月
  • 2019 年 4 月
  • 2019 年 3 月
  • 2019 年 2 月
  • 2019 年 1 月
  • 2018 年 12 月
©2021 值得您信賴的旅遊品牌 | 團體旅遊、自由行的專家‎ | Built using WordPress and Responsive Blogily theme by Superb