標籤:

Python 的 type 和 object 之間是怎麼一種關係?

是初學者請勿噴啊

兩個是互為實例的關係,但不是互為子類的關係,只有type是object的子類,反之則不成立。大牛說兩者是蛋生雞雞生蛋的關係,但我還是不明白,有懂的麻煩解釋一下,希望不要給出外文的鏈接。python為什麼設計出兩個,去掉 一個行不行?


給別人講解過很多次,但寫成文字是第一次。試一試吧,自己主要也是看了這篇文章(Python Types and Objects)才懂的。

object 和 type的關係很像雞和蛋的關係,先有object還是先有type沒法說,obejct和type是共生的關係,必須同時出現的。

在看下去之前,也要請先明白,在Python裡面,所有的東西都是對象的概念。

在面向對象體系裡面,存在兩種關係:

- 父子關係,即繼承關係,表現為子類繼承於父類,如『蛇』類繼承自『爬行動物』類,我們說『蛇是一種爬行動物』,英文說『snake is a kind of reptile』。在python里要查看一個類型的父類,使用它的__bases__屬性可以查看。

- 類型實例關係,表現為某個類型的實例化,例如『萌萌是一條蛇』,英文說『萌萌 is an instance of snake』。在python里要查看一個實例的類型,使用它的__class__屬性可以查看,或者使用type()函數查看。

這兩種關係使用下面這張圖簡單示意,繼承關係使用實線從子到父連接,類型實例關係使用虛線從實例到類型連接:

我們將使用一塊白板來描述一下Python裡面對象的關係,白板劃分成三列:

先來看看type和object:

&>&>&> object

&

&>&>&> type

&

它們都是type的一個實例,表示它們都是類型對象。

在Python的世界中,object是父子關係的頂端,所有的數據類型的父類都是它;type是類型實例關係的頂端,所有對象都是它的實例的。它們兩個的關係可以這樣描述:

- object是一個type,object is and instance of type。即Object是type的一個實例。

&>&>&> object.__class__

&

&>&>&> object.__bases__ # object 無父類,因為它是鏈條頂端。

()

- type是一種object, type is kind of object。即Type是object的子類。

&>&>&> type.__bases__

(&,)

&>&>&> type.__class__ # type的類型是自己

&

此時,白板上對象的關係如下圖:

我們再引入list, dict, tuple 這些內置數據類型來看看:

&>&>&> list.__bases__

(&,)

&>&>&> list.__class__

&

&>&>&> dict.__bases__

(&,)

&>&>&> dict.__class__

&

&>&>&> tuple.__class__

&

&>&>&> tuple.__bases__

(&,)

它們的父類都是object,類型都是type。

再實例化一個list看看:

&>&>&> mylist = [1,2,3]

&>&>&> mylist.__class__

&

&>&>&> mylist.__bases__

Traceback (most recent call last):

File "&", line 1, in &

AttributeError: list object has no attribute __bases__

實例化的list的類型是&, 而沒有了父類。

把它們加到白板上去:

白板上的虛線表示源是目標的實例,實線表示源是目標的子類。即,左邊的是右邊的類型,而上面的是下面的父親。

虛線是跨列產生關係,而實線只能在一列內產生關係。除了type和object兩者外。

當我們自己去定個一個類及實例化它的時候,和上面的對象們又是什麼關係呢?試一下:

&>&>&> class C(object):

... pass

...

&>&>&> C.__class__

&

&>&>&> C.__bases__

(&,)

實例化

&>&>&> c = C()

&>&>&> c.__class__

&

&>&>&> c.__bases__

Traceback (most recent call last):

File "&", line 1, in &

AttributeError: C object has no attribute __bases__

這個實例化的C類對象也是沒有父類的屬性的。

再更新一下白板:

白板上的第一列,目前只有type,我們先把這列的東西叫Type。

白板上的第二列,它們既是第三列的類型,又是第一列的實例,我們把這列的對象叫TypeObject。

白板上的第三列,它們是第二列類型的實例,而沒有父類(__bases__)的,我們把它們叫Instance。

你以為事情就這樣完了?不。。看見type孤零零在第一列其實不是那麼舒服。。我們給它整幾個玩伴看看。但要怎麼整呢?要屬於第一列的,必須是type的子類,那麼我們只需要繼承type來定義類就可以了:

&>&>&> class M(type):

... pass

...

&>&>&> M.__class__

&

&>&>&> M.__bases__

(&,)

&>&>&>

嗯嗯,M類的類型和父類都是type。這個時候,我們可以把它歸到第一列去。那麼,要怎麼樣實例化M類型呢?實例化後它應該出現在那個列?嗯嗯,好吧,剛才你一不小心創建了一個元類,MetaClass!即類的類。如果你要實例化一個元類,那還是得定義一個類:

&>&>&> class TM(object):

... __metaclass__ = M # 這樣來指定元類。

...

...

&>&>&> TM.__class__

& # 這個類不再是type類型,而是M類型的。

&>&>&> TM.__bases__

(&,)

好了,現在TM這個類就是出現在第二列的。

再總結一下:

第一列,元類列,type是所有元類的父親。我們可以通過繼承type來創建元類。

第二列,TypeObject列,也稱類列,object是所有類的父親,大部份我們直接使用的數據類型都存在這個列的。

第三列,實例列,實例是對象關係鏈的末端,不能再被子類化和實例化。

到現在為止,Python類型的秘密已經說穿了,不一小心連元類也暴露了。哎。慢慢消化吧,信息量很大。

如果轉述版看不懂,那麼去啃一啃原文的吧:(Python Types and Objects)

=============更新=============

更新更新。。回答一下題主在問題後面說的為什麼要有兩個,而不是一個。

如果type和object只保留一個,那麼一定是object。只有object 時,第一列將不復存在,只剩下二三列,第二列表示類型,第三列表示實例,這個和大部分靜態語言的類型架構類似,如java 。

這樣的架構將讓python 失去一種很重要的動態特性--動態創建類型。本來,類(第二列的同學)在Python裡面是一個對象(typeobject),對象是可以在運行時動態修改的,所以我們能在你定義一個類之後去修改他的行為或屬性!拿掉第一列後,第二列變成了純類型,寫成怎樣的,運行時行為就怎樣。在這一點上,並不比靜態語言有優勢。

所以,以上!


那我就來補充個跟實現思路相關的傳送門吧:先有Class還是先有Object? - RednaxelaFX 的回答

&<- 這個傳送門雖然開頭講的是Java的情況,但後面也有講Python和Ruby,相信能解答題主的一些疑惑。


------------------

PyObject

在 Python 中,所有對象都共有一些特性,這些特性定義在 PyObject 中。PyObject 定義在 Include/object.h 中:

#define PyObject_HEAD
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;

typedef struct _object {
PyObject_HEAD
} PyObject;

簡化後可以認為是這樣:

typedef struct _object {
int ob_refcnt;
struct _typeobject *ob_type;
} PyObject;

在 PyObject 中,ob_refcnt 用以記錄對象的引用數(與引用計數的內存回收相關),當有新的指針指向某對象時,ob_refcnt 的值加 1, 當指向某對象的指針刪除時,ob_refcnt 的值減 1,當其值為 0 的時候,則可以將該對象從堆中刪除(事實上並不會立即刪除)。除了 ob_refcnt 之外,還有一個 指向 _typeobject 指針ob_type,這個結構體用於表示對象類型。可以發現, Python 對象的核心在於一個引用計數和一個類型信息。

PyObject 定義的內容會出現在每個對象所佔內存的開始部分。

------------------

PyVarObject

在 Python 中,除了 bool、float 這樣的定長對象(一旦確定下來需要的內存,便不再有改動),還有另外一種對象:長度可變的對象。這種對象在 Python 的實現中通過 PyVarObject 結構體來表示:

#define PyObject_VAR_HEAD
PyObject_HEAD
Py_ssize_t ob_size; /* Number of items in variable part */

typedef struct {
PyObject_VAR_HEAD
} PyVarObject;

事實上,就是在 PyObject 的基礎上,多了一個 ob_size 變數,用以標識對象的長度(是長度,不是內存佔用)。也就是說,其實 PyVarObject 就是 PyObject 的一個拓展,於是,在 Python 中,所有的對象都可以通過 PyObject * 指針來引用,這一點非常重要,它使得很多操作變得統一(函數參數傳遞等)。

由此,Python 中所有對象在實現的時候,內存無非如下兩種情況:

定長對象 變長對象
+-----------+ +-----------+
| ob_refcnt | | ob_refcnt |
+-----------+ +-----------+
| ob_type | | ob_type |
+-----------+ +-----------+
| | | ob_size |
| | +-----------+
| other | | |
| | | other |
| | | |
+-----------+ +-----------+

------------------

PyTypeObject

在描述 PyObject 的時候,提到了一個 _typeobject 結構體。那麼,它是幹什麼的呢?想像一下,一個對象在創建的時候需要多少內存、這個對象的類名是什麼等等信息,又是如何記錄和區分的呢?

_typeobject(也就是 PyTypeObject)可以被稱之為「指定對象類型的類型對象」,其定義如下:

typedef struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; /* For printing, in format "&.&" */
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

// ...... 省略部分暫時不關心的內容

} PyTypeObject;

可以理解為,PyTypeObject 對象是 Python 中面向對象理念中「類」這個概念的實現,這裡只是簡單介紹其定義中的部分內容:

  • ty_name:類型名
  • tp_basicsize, tp_itemsize:創建類型對象時分配的內存大小信息
  • 被省略掉的部分:與該類型關聯的操作(函數指針)

這裡只是簡單描述,上面的內容有些偏頗,暫不必過分深究。

PyType_Type(Python 語言中的 type 對象)的類型就是 PyTypeObject,它是所有 class 的 class,在 Python 中叫做 metaclass。:

PyTypeObject PyType_Type = {
PyVarObject_HEAD_INIT(PyType_Type, 0)
"type", /* tp_name */
sizeof(PyHeapTypeObject), /* tp_basicsize */
sizeof(PyMemberDef), /* tp_itemsize */
(destructor)type_dealloc, /* tp_dealloc */
// ...... 省略了部分內容
};

其實,在實現中 PyType_Type 的 ob_type 指針又指向了自己本身,既是:

PyType_Type
+-----------+&<-------+ | ob_refcnt | | +-----------+ | | ob_type +--------+ +-----------+ | | | other | | | +-----------+

------------------

太晚了,說的有點馬虎,有時間再打磨打磨,完善完善吧~


class,metaclass,instance,subclass,base

以下成立:

對任意的A,A是instance(推論:任意class也是instance)

對任意A,存在B,使得B是A的class

A是class 定義為 從A可以創建B(直接或間接),使得B是A的instance

A是B的metaclass 等價於 B是class,且A是B的class(也就是class的class)

A是metaclass等價於A是class,且從A創建的instance B是class

推論:對任意A是class,存在B使得B是A的metaclass

type的metaclass是type自己

對A和B是class,A是B的base等價於B是A的subclass(這裡為了防歧義規定A不是A的subclass,可能與iasubclass不同)

A是B的base,則B不是A的base

A是B的instance當且僅當:B是A的class,或B是A的class的base

object是所有其他class的base(推論:任意A是object的instance,包括object)

推論:沒有類是object的base

type是所有其他metaclass的base

推論:object是type的base

type是object的metclass

type是type的class/metaclass

type是type的instance

object是object的instance

type是object的instance

object是type的instance

注意:metaclass的base不一定是metaclass

class與instance,base與subclass只是兩種正交的關係,它們通過isinstance相互聯繫,在Python中並不要求它們有先後順序

=================================================

我補充一下什麼叫做「不要求有先後順序」,實際上在Python當中自定義類的__bases__,自定義實例的__class__是可以修改的……

&>&>&> class A(object): pass
...
&>&>&> class B(object): pass
...
&>&>&> class C(A): pass
...
&>&>&> c = C()
&>&>&> c.__class__
&
&>&>&> C.__bases__
(&,)
&>&>&> isinstance(c, C)
True
&>&>&> isinstance(c, A)
True
&>&>&> isinstance(c, B)
False
&>&>&> issubclass(C, A)
True
&>&>&> issubclass(C, B)
False
&>&>&> C.__bases__ = (B,)
&>&>&> issubclass(C, A)
False
&>&>&> issubclass(C, B)
True
&>&>&> isinstance(c, A)
False
&>&>&> isinstance(c, B)
True
&>&>&> c.__class__ = A
&>&>&> isinstance(c, C)
False
&>&>&> isinstance(c, B)
False
&>&>&> isinstance(c, A)
True

本質上來說就是一個指向的關係,想怎麼改就可以怎麼改,只要不違背我上面所說的法則就行。Python里的class和instance就是這樣沒有節操的東西……

我們下面來造一個A是B的metaclass,B是A的base的例子:

&>&>&> class A(type): pass
...
&>&>&> class B(metaclass=A): pass
...
&>&>&> A.__bases__ = (type, B)
&>&>&> isinstance(B, A)
True
&>&>&> issubclass(A, B)
True
&>&>&> isinstance(B, B)
True

由於Python實現的問題,不是所有的__bases__和__class__都可以隨意指定(有一些限制),但大體上可以理解為就是個可以改的指針


謝邀,object是type(object的類型是type),type也是object(type繼承自object)

&>&>&> isinstance(object, type)
True
&>&>&> isinstance(type, object)
True

在python中一切皆object,所有對象都是從object繼承而來的,type也是object,而object的type是type

&>&>&> type.__base__
&
&>&>&> type(object)
&

1、type是一切type的類型

2、object是所有對象的基類,type也繼承自object

3、object的type是type

借用某博客里的一張圖片,他們的關係應該是這樣的(藍色表示繼承,紅色表示類型)

去掉object所有對象都不能用了,而去掉type,所有對象還是可以正常運作的,只是沒有一個東西標識他的類型了,至於為什麼可以去掉type,python的type和object之間是怎麼一種關係? - 劉鑫的回答 說的很清楚,這裡就不補充了


其他回答比較詳細了,我就一圖頂千言吧


這部分我當初是讀MSDN里關於C Sharp的Object 和 type 的關係讀懂的……你如果手邊有Jeffery的《CLR via C#》 可以讀一下。專門為了這個問題去買一本可能有點奢侈,不過如果你是 .net 程序員,我推薦你收一本。

簡單的說,很多運行時體系(不一定是針對某種語言)都提供在運行時獲取類型信息的功能,那麼獲取出來的是什麼東西呢?獲取出來的是一個描述類型信息的對象。那麼所有描述類型信息的對象,都是「類型」這個類型的實例。這個type類型不是類型本身,而是用於描述類型的對象實例,類型本身是一種抽象的信息,type類的實例對象是它具體的信息載體。既然type類型也是一種類型,那麼它是公共根類型object的一個派生,也就是合情合理的設計了。

反過來,object 類型並不依賴 type 類型,最多它的一些反射/自省邏輯需要調用type


既不是互為實例:

&>&>&> object.__class__

&

&>&>&> type.__class__

&

也不是互為子類:

&>&>&> object.__bases__

()

&>&>&> type.__bases__

(&,)

type和object都是type的實例,而type是object的子類。

__class__是這兩個關係中更基本的一個。所有Python對象都有對應的class對象,而對一個Python的幾乎所有操作,即使是訪問對象屬性o.a這麼基本的,都是轉交給其class對象執行。唯二的例外,是__class__和id,這兩個操作的語義無法被class對象改變。在這方面,Python的可定製程度比絕大部分OOPL要高。

type是所有class對象的class,也稱為metaclass。它決定了你直接操作class對象(而不是通過其實例)時的行為。例如:

class C(object):
a = 1
def f(self):
pass
c = C()
c.f() # 行為由C決定
C.a # 行為由type決定

Python並未規定class一定要(直接或間接地)以type作為metaclass。

至於父類-子類關係,之所以說是兩個關係中較弱的一個,因為「一個class有父類」只是metaclass為type的那些class的行為。如果你自己不從type創建一個class(需要使用Python C API),它也可以沒有父類這個概念。

由於type本身也是一個class,並且以自身為metaclass,因此它也以object為祖先。object給所有「以type為(直接或間接的)metaclass創建的class的實例」(實際上包括了所有Python built-in objects和純Python代碼創建的對象)提供了預設行為。

至於能否將type和object合併,回顧:

type給所有class對象指定行為

object給所有對象提供預設行為

type里有一些只對class對象有意義的方法,比如mro()。並且type假設其實例都有class必須定義的一堆屬性(比如class都要有__new__)。如果與object合併成object_type,那麼:

所有對象都從object_type繼承了只對class對象有意義的mro等方法

所有對象都必須有class對象的一堆屬性,從而內存佔用變大


我先放張圖

圖對不對先不管。我們先來看看 type 和 object 分別是什麼。type 實際上是:

#define PyVarObject_HEAD_INIT(type, size)
1, type, size,

PyTypeObject PyType_Type = {
PyVarObject_HEAD_INIT(PyType_Type, 0)
"type", /* tp_name */
sizeof(PyHeapTypeObject), /* tp_basicsize */
sizeof(PyMemberDef), /* tp_itemsize */
0, /* tp_base */
...
}

object 實際上是:

PyTypeObject PyBaseObject_Type = {
PyVarObject_HEAD_INIT(PyType_Type, 0)
"object", /* tp_name */
sizeof(PyObject), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_base */
...
}

也就是說,type 和 object 的前兩個欄位是一樣的,都是1和 PyType_Type

ob_refcnt = 1 // 引用計數
ob_type = PyType_Type // 指向一個類型對象,用來指定當前對象的類型

即,type 和 object 的 ob_type 都是 PyType_Type,而PyType_Type就是 type,所以 type 的ob_type 是自己。

我們來看看 isinstance() 做了什麼:

#define Py_TYPE(ob) (((PyObject*)(ob))-&>ob_type)

[abstract.c]
PyObject_IsInstance(PyObject *inst, PyObject *cls)
{
static PyObject *name = NULL;

/* Quick test for an exact match */
if (Py_TYPE(inst) == (PyTypeObject *)cls)
return 1;
...
}

isinstance() 做的事情其實很簡單,就是判斷inst -&> ob_type 指向的類型是不是 (PyTypeObject *)cls。

instance(object,type) &<==&> if object.ob_type == type return 1 else return 0;

從前面可以看到 ob_type = PyType_Type,而 PyType_Type 就是 type,所以,顯然object 被判斷為了 type 的實例。

實際上他們在代碼實現上並沒有類與實例的關係,但是在判斷的時候強加了這層關係。

================實例的關係說完了,下面說說繼承關係===================

我們來看看 issubclass():

[abstract.c]
PyObject_IsSubclass(PyObject *derived, PyObject *cls)
{
...
return recursive_issubclass(derived, cls);
}
//最終轉化成
[typeobject.c]
int PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b)
{
mro = a-&>tp_mro;
if (mro != NULL) {
...
}
else{
do {
if (a == b)
return 1;
a = a-&>tp_base;
} while (a != NULL);
return b == PyBaseObject_Type; //這一句!
}
}

從上面我們也可以看出 python 的繼承機制。

我們也可以看到,如果一個類沒有基類,那他的父類就是object ,即便在代碼實現上它並沒有基類,但是在 issubclass()中就是這樣認為的!

那 type 到底有沒有基類呢?目前我還沒有找到 ,我會繼續找的。即便有也只是給個標誌位標識一下,並沒有什麼特殊的動作。

type 和 object 在代碼實現上時平行的,沒有父子類的關係,但是在判斷的時候,開發者將 type 判斷為了 object 的子類,以滿足python 對外呈現的思想。

python 對外呈現的思想是:

object :是一切類的基類
type :一切類型都是它的實例

但實際上它的代碼實現並不符合這樣的思想,C 語言本身也沒有類和繼承的概念,開發者做了一些處理,讓他們看起來是符合思想的。

總結:type 和 object 其實並沒有繼承與實例化的關係,只是開發者為了保持 python 純正的思想,給他們添加了聯繫。添加聯繫的方式有兩種:一種是設置標誌位,如ob_type,一種是函數判斷中做特殊處理(就像 PyType_IsSubtype 函數那樣)。

最後,我沒看出哪裡有涉及到自舉,哪位大神指點下?


  1. 所有對象都一定是某一個類的實例
  2. 在python中類也是對象,所有類都是type元類的實例

  3. type元類也是對象,它是它自己的實例,它的父類是object

  4. object是類,它是type的實例,object沒有父類

我想這大概是是為了完成完全的面向對象,既然萬物都是對象,那最源頭的對象又是誰的實例?type和object很好地解決了這個問題:抓著自己的鞋帶把自己提起來(bootstrap)。

python新手,說錯請指正。


Python中一切皆對象,凡事對象都有類型。

從cpython/object.h at 2.7 · python/cpython · GitHub

/* PyObject_HEAD defines the initial segment of every PyObject. */
#define PyObject_HEAD
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;

可以看到每一個object中都有一個 ob_type 的指針,指向了某一個具體的類型。

而type本身也是一個對象,不同的object本身的會有一個type

上代碼演示一下或許會更清晰一些:

In [1]: a = 1

In [2]: type(a)
Out[2]: int

In [3]: type(int)
Out[3]: type

In [4]: type(type)
Out[4]: type

上面的代碼中可以看到 object a,*ob_type 會指向 int,int 是 1 的type,同時也是一個type,而int 本身的*ob_type 則指向了 type

Python中的對象按照比較方便的理解來區分的話,可以分為 普通對象 跟 類型對象,普通對象的 type 就是 int,str 之類的類型, 而類型對象的類型,則是type

In [1]: class NewData(object):
...: pass
...:

In [2]: newdata = NewData()

In [3]: NewData.__class__
Out[3]: type

In [4]: type(NewData)
Out[4]: type

In [5]: newdata.__class__
Out[5]: __main__.NewData

In [6]: type(newdata)
Out[6]: __main__.NewData

In [7]: type.__class__
Out[7]: type

In [8]: type.__base__
Out[8]: object

In [9]: NewData.__base__
Out[9]: object

In [10]: type(object)
Out[10]: type

In [11]: object.__class__
Out[11]: type


之前讀過一篇討論這個問題文章,鏈接已經丟了。。。建議題主讀一讀《Ruby元編程》,這本書對類和對象有較清晰和深入的討論,要求不高,Ruby和Python的對象模型非常相似,不懂Ruby也能讀懂。

要搞懂這個問題,首先要先把類、類型、對象這些概念全部舍掉,重構世界觀。

首先,python裡面一切皆是對象,包括type、object、所有class,全部都是對象,

那對象之間靠什麼聯繫在一起呢?沒錯,靠的就是關係:

Python的世界裡,對象之間一共有兩種關係:

1、繼承關係:

比如有class A和class B(A),再強調一下,A和B都是對象,

則對象B繼承了對象A,或者說A是B的超類,

繼承關係可以通過__base__屬性得知,

&>&>&> B.__base__
&

在python里,所有對象(包括type)均繼承自object,而object則是繼承體系的根,上面再無對象:

&>&>&> object.__base__
&>&>&> type.__base__
&

2、實例關係

比如有class A, a = A(),不嫌煩的再強調一下,a和A都是對象,

則對象a是對象A的實例,或者說對象A是對象a的類型,

實例關係可通過__class__屬性獲知:

&>&>&> a.__class__
&

在python里,對象又可以分為三種:type object、class object和non-class object,

type object指type對象及其子類,如:

class TypeA(type): pass

則TypeA和type均屬於type object

class object
指obect對象及其子類,如:

class A(object):pass

則object和A均屬於class object

non-class object指通過實例化class object得來的對象,如

a = A()

則a就是一個non-class object

三者的區別和聯繫在於:

type object都是type的實例,

class object是type object的實例,

non-class object是class object的實例,

type object和class object都可以進行實例化,

而non-class object不能進行實例化

在python的世界裡,type object和class object這兩種類型的對象都是type對象的實例

而type屬於type object,object屬於class object,則顯然:

&>&>&> object.__class__
&
&>&>&> type.__class__
&


首先了解2條規則

  1.若x是A的一個實例,且A是B的子類,那麼x也是B的一個實例

  2.若B是M的實例,且A是B的子類,那麼A也是M的一個實例

  首先type為object的子類,(A=type,B=object)

  &>&>&> issubclass(type,object) True

  其次object是type的實例(x=object,A=type)

  &>&>&> isinstance(object,type) True

  規則1得出object是object的實例(B=object,M=object)

  &>&>&> isinstance(object,object) True

  規則2得出type是object的實例

  &>&>&> isinstance(type,object) True

  同樣可以得到type是type自己實例

  &>&>&> isinstance(type,type) True


在Python的C源碼中,用結構體表示Python的類;每個表示類的結構體的第二個欄位都是一個指向PyTypeObject對象的指針;這個PyTypeObject就是類型對象(type得到的東西),每一個類的對象共用一個PyTypeObject對象(所以用的指針)。在python中只要有引用計數(一個long的整型),指向PyTypeObject的指針就可以成為類。


這個。。。怎麼說呢

你要看py2還是py3

我這裡說我比較熟的py3

在py3中「萬物皆對象」

object是對象

class也是對象

type還是對象

py3中每個對象都有一個類型(類型也是個對象,也有類型)

object的類型是class name

class的類型是 TypeType

Type的類型是 TypeType

換句話來說 class在py3中等於type

在Python中每個對象中都包含一個類型對象

// [ object.h ]

struct _object {

...

struct PyType_Object *tp:

...

} PyObject;

-----------------------

class A:

pass

a = A()

[ REPL ]:

λ type(A)

=&> type

λ type(a)

=&> A

λ type(type(a))

=&> type

嘿嘿,聽著是不是特絕望?

我當初也被繞暈了

肥腸抱歉的是,因為移動的逼網出問題了

我是在手機上編輯的,所以沒法調好看的縮進和代碼樣式


1,理解生活中的栗子

2. python metaclass,即我們說的 class type的兩面性

class type是類(本質是模具,作用是生產磨具),那麼你說他生產的磨具不是他的實例嗎? 而他生產的實例又是類.

[類與實例關係]class type是一種特殊的類,它的實例有兩面性
站在class type角度講, 他的實例有class str,class dict等,也就是class str, class dict是實例. 這些實例最高父類是object.
站在class str,class dict角度講,他們是類, 可以創造各自的實例. 這些實例不存在父類的概念

3.好了,理解了 class type創造出的類有兩面性,那麼在想想生活中的栗子吧. 很多人yy了,靠.越說越複雜.


分頁阅读: 1 2