日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

通過 Type 和 Object 之間的關聯,進一步分析類型對象

來源: 責編: 時間:2024-05-20 08:49:59 240觀看
導讀楔子type 和 object 兩者的關系估計會讓很多人感到困惑,我們說 type 站在類型金字塔的頂端,任何對象按照類型追根溯源,最終得到的都是 type。而 object 站在繼承金字塔的頂端,任何類型對象按照繼承關系追根溯源,最終得到的

楔子

RJS28資訊網——每日最新資訊28at.com

RJS28資訊網——每日最新資訊28at.com

type 和 object 兩者的關系估計會讓很多人感到困惑,我們說 type 站在類型金字塔的頂端,任何對象按照類型追根溯源,最終得到的都是 type。而 object 站在繼承金字塔的頂端,任何類型對象按照繼承關系追根溯源,最終得到的都是 object。RJS28資訊網——每日最新資訊28at.com

因此我們可以得出以下結論:RJS28資訊網——每日最新資訊28at.com

RJS28資訊網——每日最新資訊28at.com

  • type 的父類是 object
  • object 的類型是 type

驗證一下:RJS28資訊網——每日最新資訊28at.com

print(type.__base__)  # <class 'object'>print(object.__class__)  # <class 'type'>

打印結果說明結論正確,但這就奇怪了,type 的父類是 object,而 object 的類型又是 type,那么問題來了,是先有 type 還是先有 object 呢?帶著這些疑問,開始下面的內容。RJS28資訊網——每日最新資訊28at.com

RJS28資訊網——每日最新資訊28at.com

類是由誰創建的

RJS28資訊網——每日最新資訊28at.com

RJS28資訊網——每日最新資訊28at.com

首先必須要澄清一個事實,類對象的類型是 type,這句話是沒有問題的。但如果說類對象都是由 type 創建的,就有些爭議了。因為 type 能夠創建的是自定義的類,而內置的類在底層是預先定義好的。RJS28資訊網——每日最新資訊28at.com

# int、tuple、dict 等內置類型# 在底層是預先定義好的,以全局變量的形式存在# 我們直接就可以拿來用print(int)  # <class 'int'>print(tuple)  # <class 'tuple'># 但對于自定義的類,顯然就需要在運行時動態創建了# 而創建這一過程,就交給 type 來做class Girl:    pass

然后 type 也只能對自定義類進行屬性上的增刪改,內置的類則不行。RJS28資訊網——每日最新資訊28at.com

class Girl:    pass# 給類對象增加一個成員函數type.__setattr__(    Girl,    "info",    lambda self: "name: 古明地覺, age: 17")# 實例化之后就可以調用了print(Girl().info())  # name: 古明地覺, age: 17# 但內置的類對象,type 是無法修改的try:    type.__setattr__(int, "a", "b")except TypeError as e:    print(e)"""TypeError: cannot set 'a' attribute of immutable type 'int'"""

上一篇文章中我們說了,Python 所有的類型對象(包括 type)都是由 PyTypeObject 結構體實例化得到的,只不過結構體字段的值不同,得到的類也不同。并且內置的類型對象在底層是預定義好的,它們在解釋器看來是同級別的,不存在誰創建誰。RJS28資訊網——每日最新資訊28at.com

而每一個對象都有引用計數和類型,然后解釋器將這些類對象的類型都設置成了 type,我們舉例說明。不過在此之前,需要先說一個宏。RJS28資訊網——每日最新資訊28at.com

// Include/object.h// _PyObject_EXTRA_INIT 可以忽略掉// 然后我們看到這個宏是用來初始化引用計數和類型的// 并且引用計數的值為 uint32 類型的最大值,因此創建的是永恒對象#define PyObject_HEAD_INIT(type)    /    {                               /        _PyObject_EXTRA_INIT        /        { _Py_IMMORTAL_REFCNT },    /        (type)                      /    },    // 用于初始化引用計數、類型和 ob_size#define PyVarObject_HEAD_INIT(type, size) /    {                                     /        PyObject_HEAD_INIT(type)          /        (size)                            /    },

下面我們來看幾個類型對象。 RJS28資訊網——每日最新資訊28at.com

圖片圖片RJS28資訊網——每日最新資訊28at.com

我們看到所有類型對象的類型都被設置成了 &PyType_Type,也就是 Python 里的 type。所以結論很清晰了,雖然內置的類型對象可以看做是 type 的實例對象,但它卻不是由 type 實例化得到的,而是在底層預定義好,并以全局變量的形式靜態出現。RJS28資訊網——每日最新資訊28at.com

所以內置的類型對象之間不存在誰創建誰,它們都是預定義好的,只是在定義的時候,將自身的類型設置成了 type 而已,包括 type 本身(類型還是 type)。這樣一來,每一個對象都會具有一個類型,從而將面向對象理念貫徹的更加徹底。RJS28資訊網——每日最新資訊28at.com

print(int.__class__)print(tuple.__class__)print(set.__class__)print(type.__class__)"""<class 'type'><class 'type'><class 'type'><class 'type'>"""print(    type.__class__.__class__.__class__ is type)  # Trueprint(    type(type(type(type(type(type))))) is type)  # True

好,說完了這些之后我們來正式考察 type 和 object 的底層實現。RJS28資訊網——每日最新資訊28at.com

RJS28資訊網——每日最新資訊28at.com

類型對象的類型:PyType_Type

RJS28資訊網——每日最新資訊28at.com

RJS28資訊網——每日最新資訊28at.com

type 是所有類型對象的類型,我們稱之為元類型或者元類,即 metaclass,當然它同時也是一個類型對象。下面看一下它的底層實現。RJS28資訊網——每日最新資訊28at.com

// Objects/typeobject.cPyTypeObject PyType_Type = {    PyVarObject_HEAD_INIT(&PyType_Type, 0)    "type",                                     /* tp_name */    sizeof(PyHeapTypeObject),                   /* tp_basicsize */    sizeof(PyMemberDef),                        /* tp_itemsize */    (destructor)type_dealloc,                   /* tp_dealloc */    offsetof(PyTypeObject, tp_vectorcall),      /* tp_vectorcall_offset */    0,                                          /* tp_getattr */    0,                                          /* tp_setattr */    0,                                          /* tp_as_async */    (reprfunc)type_repr,                        /* tp_repr */    &type_as_number,                            /* tp_as_number */    0,                                          /* tp_as_sequence */    0,                                          /* tp_as_mapping */    0,                                          /* tp_hash */    (ternaryfunc)type_call,                     /* tp_call */    // ...};

所有的類型對象加上元類都是由 PyTypeObject 這個結構體實例化得到的,所以它們內部的字段都是一樣的。只不過傳入的值不同,實例化之后得到的結果也不同,可以是 PyLong_Type、可以是 PyFloat_Type,也可以是這里的 PyType_Type。RJS28資訊網——每日最新資訊28at.com

再看一下里面的宏 PyVarObject_HEAD_INIT,它用來初始化引用計數、類型和 ob_size,其中類型被初始化成了 &PyType_Type。換句話說,PyType_Type 里面的 ob_type 字段指向的還是 PyType_Type,而對應 Python 的話,就是 type 的類型還是 type。RJS28資訊網——每日最新資訊28at.com

>>> type.__class__<class 'type'>>>> type.__class__.__class__.__class__.__class__.__class__ is typeTrue>>> type(type(type(type(type(type))))) is typeTrue

顯然不管套娃多少次,最終的結果都是True,這也是符合預期的。RJS28資訊網——每日最新資訊28at.com

RJS28資訊網——每日最新資訊28at.com

類型對象的基類:PyBaseObject_Type

RJS28資訊網——每日最新資訊28at.com

RJS28資訊網——每日最新資訊28at.com

Python 中有兩個類型對象比較特殊,一個是站在類型金字塔頂端的 type,另一個是站在繼承金字塔頂端的 object。看完了 type,再來看看 object。RJS28資訊網——每日最新資訊28at.com

由于 object 的類型是 type,那么在初始化 PyBaseObject_Type 的時候,它的 ob_type 一定也被設置成了 &PyType_Type。RJS28資訊網——每日最新資訊28at.com

我們看一下 PyBaseObject_Type 的實現,它同樣定義在 Objects/typeobject.c 中。RJS28資訊網——每日最新資訊28at.com

圖片圖片RJS28資訊網——每日最新資訊28at.com

類型對象在創建的時候,ob_type 字段都會被初始化成 &PyType_Type,而 object 也不例外,所以它的類型為 type,這個非常簡單。但 type 的基類是 object,又是怎么一回事呢?RJS28資訊網——每日最新資訊28at.com

之前介紹類型對象的時候,我們說類型對象內部的 tp_base 表示繼承的基類,那么對于 PyType_Type 來講,它內部的 tp_base 肯定是 &PyBaseObject_Type,即 object。RJS28資訊網——每日最新資訊28at.com

圖片圖片RJS28資訊網——每日最新資訊28at.com

但令我們吃鯨的是,它的 tp_base 居然是個 0,如果為 0 的話則表示沒有這個屬性,或者說基類為空。不是說 type 的基類是 object 嗎?為啥 tp_base 是 0 呢。RJS28資訊網——每日最新資訊28at.com

事實上如果你去看其它類型的話,會發現它們內部的 tp_base 也是 0。為 0 的原因就在于我們目前看到的類型對象還不夠完善,因為 Python 的動態性,顯然不可能在定義的時候就將所有字段屬性都設置好、然后解釋器一啟動就得到我們平時使用的類型對象。RJS28資訊網——每日最新資訊28at.com

因此目前看到的類型對象還不是最終形態,有一部分字段屬性是在解釋器啟動之后再動態完善的,而這個完善的過程被稱為類型對象的初始化,它由函數 PyType_Ready 負責。RJS28資訊網——每日最新資訊28at.com

圖片圖片RJS28資訊網——每日最新資訊28at.com

首先代碼中的 type 只是一個普通的參數,當解釋器發現一個類對象還沒有初始化時,會將其作為參數傳遞給 PyType_Ready,進行初始化。RJS28資訊網——每日最新資訊28at.com

初始化過程會做很多的工作,用于完善類型對象,而其中一項工作就是設置基類。如果發現類型對象的基類為空,那么就將基類設置為 object,因為在 Python3 里面新式類都要繼承 object。當然啦,這個類不能是 object 本身,object 的基類是 None,因為繼承鏈向上要有一個終點。RJS28資訊網——每日最新資訊28at.com

當 PyType_Ready 完成初始化之后,就得到我們平常使用的類型對象了,最終 PyType_Type 和 PyBaseObject_Type 的關系如下。RJS28資訊網——每日最新資訊28at.com

圖片圖片RJS28資訊網——每日最新資訊28at.com

因此到目前為止,type 和 object 之間的恩怨糾葛算是真相大白了,總結一下:RJS28資訊網——每日最新資訊28at.com

1)和自定義類不同,內置的類不是由 type 實例化得到的,它們都是在底層預先定義好的,不存在誰創建誰。只是內置的類在定義的時候,它們的類型都被設置成了 type。這樣不管是內置的類,還是自定義類,在調用時都會執行 type 的 __call__ 函數,從而讓它們的行為是一致的。RJS28資訊網——每日最新資訊28at.com

2)雖然內置的類在底層預定義好了,但還有一些瑕疵,因為有一部分邏輯無法以源碼的形式體現,只能在解釋器啟動的時候再動態完善。而這個完善的過程,便包含了基類的填充,會將基類設置成 object。RJS28資訊網——每日最新資訊28at.com

所以 type 和 object 是同時出現的,它們的存在需要依賴彼此。首先這兩者會以不完全體的形式定義在源碼中,并且在定義的時候將 object 的類型設置成 type;然后當解釋器啟動的時候,再經過動態完善,進化成完全體,而進化的過程中會將 type 的基類設置成 object。RJS28資訊網——每日最新資訊28at.com

所以 object 的類型是 type,type 繼承 object 就是這么來的。RJS28資訊網——每日最新資訊28at.com

RJS28資訊網——每日最新資訊28at.com

小結

RJS28資訊網——每日最新資訊28at.com

RJS28資訊網——每日最新資訊28at.com

至此,我們算是從解釋器的角度完全理清了 Python 中對象之間的關系,用之前的一張圖總結一下。RJS28資訊網——每日最新資訊28at.com

圖片圖片RJS28資訊網——每日最新資訊28at.com

當然,目前還遠遠沒有結束,后續還會針對內置的對象進行專門的剖析,如浮點數、整數、字符串、字節串、元組、列表、字典、集合等等,都會一點一點剖析。我們會從 Python 的角度介紹對象該怎么用,然后再看它的底層實現,最后再用 Python 代碼進行驗證,加深理解。RJS28資訊網——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-89225-0.html通過 Type 和 Object 之間的關聯,進一步分析類型對象

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 全方位保護!OPPO Reno12 系列搭載多項防護新科技

下一篇: 十個 Python 高效列表推導式秘籍

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
亚洲深夜福利| 亚洲精选大片| 国产精品社区| 国产亚洲精品aa午夜观看| 激情婷婷久久| 日韩视频在线播放| 午夜精品99久久免费| 久久综合网色—综合色88| 欧美精品在线一区二区| 国产精品乱子乱xxxx| 一区二区三区在线视频播放| 亚洲乱码国产乱码精品精98午夜| 亚洲一区二区三区在线观看视频| 久久精品国产久精国产思思| 欧美母乳在线| 国产农村妇女精品一二区| 国产欧美精品日韩| 91久久久久久久久久久久久| 亚洲欧美日韩国产成人| 欧美 日韩 国产精品免费观看| 欧美日韩一区二区三区在线| 国产真实乱偷精品视频免| 亚洲理论在线| 久久精品亚洲精品| 欧美色欧美亚洲高清在线视频| 狠狠色丁香久久婷婷综合丁香| 99在线精品视频| 久久夜色精品亚洲噜噜国产mv| 欧美午夜精品久久久久久人妖| 狠狠色综合日日| 亚洲一区国产一区| 欧美成人午夜激情| 国产日韩在线看片| 在线视频欧美一区| 免费不卡视频| 国产欧美精品一区| 制服丝袜激情欧洲亚洲| 老司机一区二区三区| 国产精品综合| 日韩一级免费| 免费亚洲一区| 国产一区二区看久久| 亚洲最新色图| 欧美fxxxxxx另类| 国产亚洲精品久久久| 亚洲一级影院| 欧美日韩中文字幕在线| 在线免费观看欧美| 欧美伊人精品成人久久综合97| 欧美色图麻豆| 亚洲精品国产精品国产自| 久久久久.com| 国产视频综合在线| 销魂美女一区二区三区视频在线| 欧美日韩精品中文字幕| 亚洲黄色一区二区三区| 久久久亚洲欧洲日产国码αv| 国产精品一区二区男女羞羞无遮挡 | 亚洲免费成人av电影| 久久综合九色综合久99| 国产真实乱偷精品视频免| 亚洲欧美国产高清| 欧美午夜精品| 中国亚洲黄色| 欧美日韩另类综合| 日韩视频在线免费观看| 欧美国产综合一区二区| 亚洲激情网址| 欧美成人午夜| 亚洲黄一区二区| 欧美77777| 91久久在线观看| 男女视频一区二区| 在线看欧美日韩| 噜噜噜噜噜久久久久久91 | 国产欧美日韩不卡免费| 亚洲在线免费视频| 欧美揉bbbbb揉bbbbb| 999亚洲国产精| 欧美日韩国产限制| 亚洲激情一区| 欧美噜噜久久久xxx| 亚洲乱码精品一二三四区日韩在线| 免费人成精品欧美精品| 在线观看亚洲精品| 免费欧美在线视频| 91久久久一线二线三线品牌| 欧美精品aa| 一本色道久久99精品综合| 欧美三级在线视频| 亚洲一区二区三区在线| 国产欧美精品一区二区三区介绍| 午夜精品一区二区三区在线| 国产美女精品| 久久精品首页| 亚洲国产日韩综合一区| 欧美精品偷拍| 亚洲一级片在线观看| 国产麻豆综合| 久久尤物视频| 亚洲精选大片| 国产精品国色综合久久| 欧美专区第一页| 在线精品视频免费观看| 欧美精品一区视频| 亚洲在线视频| 国内视频一区| 欧美国产欧美亚洲国产日韩mv天天看完整| 日韩亚洲视频在线| 国产精品一区二区三区观看 | 欧美黄色成人网| 一区二区三区国产盗摄| 国产精品一区三区| 老司机成人在线视频| 99精品欧美一区二区蜜桃免费| 国产精品剧情在线亚洲| 久久久久综合一区二区三区| 亚洲日本中文| 国产伦精品一区二区三区在线观看| 久久久人成影片一区二区三区观看| 91久久精品视频| 国产精品成人播放| 久久久综合香蕉尹人综合网| 亚洲免费观看| 国产亚洲精品久久久久婷婷瑜伽| 蜜桃av一区二区| 亚洲一区欧美激情| 在线不卡亚洲| 国产精品久久久久77777| 久久久亚洲国产天美传媒修理工| 日韩午夜中文字幕| 国产视频在线观看一区二区三区 | 日韩午夜中文字幕| 国产亚洲电影| 欧美日韩免费观看一区=区三区| 欧美一区二区精品久久911| 亚洲黑丝在线| 国产精品日本| 欧美福利影院| 久久se精品一区二区| 日韩午夜三级在线| 精品动漫3d一区二区三区| 欧美色综合网| 美女日韩在线中文字幕| 午夜精品免费在线| 亚洲伦理久久| 伊人成人在线| 国产精品专区一| 欧美人在线观看| 久久久777| 亚洲综合社区| 99re6这里只有精品视频在线观看| 国产午夜精品一区二区三区欧美| 欧美日韩不卡合集视频| 久久亚洲欧美| 欧美一区二区三区四区在线| av成人黄色| 亚洲国产精品一区二区www在线| 国产乱码精品1区2区3区| 欧美另类69精品久久久久9999| 久久人91精品久久久久久不卡| 亚洲影视在线| 日韩一本二本av| 在线视频成人| 国产曰批免费观看久久久| 国产精品ⅴa在线观看h| 欧美顶级大胆免费视频| 久久欧美中文字幕| 欧美一区二区在线免费播放| 亚洲天堂成人| 亚洲美女黄色片| 亚洲国产成人高清精品| 国产视频在线观看一区二区三区| 国产精品久久久久久久午夜片 | 欧美福利视频网站| 久久综合综合久久综合| 欧美一区二区三区四区在线| 亚洲一区二区在线免费观看视频| 亚洲伦理在线免费看| 亚洲国产激情| 影音先锋在线一区| 国内精品免费午夜毛片| 国产精自产拍久久久久久| 欧美视频一区二区在线观看| 欧美人与禽猛交乱配视频| 欧美成人有码| 免费在线播放第一区高清av| 久久亚洲综合色| 鲁大师影院一区二区三区| 久久久亚洲精品一区二区三区| 欧美在线观看网站| 欧美一区视频在线| 亚洲欧美日韩在线高清直播| 亚洲在线视频| 西瓜成人精品人成网站| 午夜激情综合网| 亚洲欧美日韩高清| 午夜精品视频| 欧美在线观看视频| 欧美一级视频精品观看| 欧美一区二区三区视频免费播放 | 久久精品国产久精国产一老狼| 久久成人18免费网站| 久久久www免费人成黑人精品 |