在將對象的創建和行為之前,我們先來看一下類型對象,python是弱類型語言,但並不代表python沒有類型,python中處理對象的類型有一個專門的對象,我們稱之為類型對象,如果不知道對象的類型就無法為對象開闢內存空間,因為佔用內存的大小是對象的元信息,是對象的基本信息,這與對象所屬類型密切相關,因此,他一定回出現在python對象所對應的類型物件中,開啟python原始碼中的include資料夾的object.h文件,檢視PyTypeObject的來源碼,在大約第324行:
typedef struct _typeobject {
, in format "
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */
printfunc tp_print;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
cmpfunc tp_compare;
reprfunc tp_repr;
as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;
/* More standard operations (here for ary compatibility) */
hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str _setattro;
/* Functions to access object as input/output buffer */
PyBufferProcs *tp_as_buffer
🜎 to define presence of optional/expanded features */
long tp_flags;
const char *tp_doc /* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
arisons */
richcmpfunc tp_richcompare;
/* weak reference enabler */
Py_ssize_t tp_weaklistoffset;
/* Added in release 2.2 */
/* Iterators */
/* Attribute descriptor and subclassing stuff */
struct PyMethodDef *tp_methods;
struct PyMemberDef *tp_members;
struct PyGetSetDef *tp_getset;
struct _typeobject *tp_base;
PyObject *tp_dict;
_cr ;
Py_ssize_t tp_dictoffset;
initproc tp_init;
allocfunc tp_alloc;
/tp 是;
PyObject *tp_subclasses;
PyObject *tp_weaklist;
destructor tp_del;
/* 類型 attribute cache version tag. Added in version 2.6 */
unsigned int tp_version_tag; explicitly initialized */
Py_ssize_t tp_allocs;
Py_ssize_t tp_frees;
Py_ssize_t tp_maxalloc;
struct _typeobject *tp_prev;
struct _typeobject *tp_next;
#endif
} PyTypeObject;上面這段程式碼很長,一個結構體100多行,不過所包含的資訊主要分為如下四大類:
1、型別名,tp_name,主要是python內部以及調試時使用,用來識別對象的所屬類型;
2、tp_basicsize和tp_itemsize,建立該類別物件分配記憶體空間的大小的資訊;
3、與該類別物件關聯的操作訊息,例如說tp_base等指向函數的指標;
4、類型物件的類型資訊。
重點1、物件的建立:
python建立物件主要有兩種方法,Python C API和PyInt_Type。
Python C API讓使用者從C環境與Python交互,一共有兩種API,一種是AOL(Abstract Object Layer)即泛型API,另一種是COL(Concrete Object Layer)即類型API;AOL都有PyObject_***的形式,可以應用在任何Python物件上,表達式一般表示為:PyObject* intObj = PyObject_new(PyObject,&PyInt_Type),而COL的API一般如下:PyObject* intObj = PyInt_FromLong(1000);我們就創建了一個1000整數物件。
無論採用哪種Python C API,Python都是最終直接分配內存,因為這都是Python的內建對象,而如果我們自己定義了一個類別如:class MySelf(object),對於類型MySelf,Python不會使用API來創建,但Python會透過MySelf所對應的類型物件來建立實例對象, MySelf的類型物件是object,所有Python都會透過object來建立MySelf的實例化物件。我們執行以下程式碼:
class A(object):
pass
a = A()
type(a)
A.__base__
結果
實際上,Python是先實例化object運行object的建構方法,然後再實例化A,這與Python的底層實現有著密切的聯繫。任何一個使用者自訂的Python類,最後都有一個共同的父類object,實例化時先實例化object類,一次向下,直到實例化使用者自訂的類別。
Screen Shot 2014-06-14 at 下午12.01.15
物件的行為:
在物件的操作資訊中有三組非常重要的操作族,tp_as_number,tp_as_sequence,tp_as_ocpingytpPestm,PMapPencePotPentft 。對於一個對象,他可以同時定義三個函數族中的所有操作,即對象可以表現出數值對象的特性和關聯對象的特性,代碼如下:
class MyInt(int):
def __getitem__(self ,key):
return key+str(self)
a = MyInt(1)
b = MyInt(2)
print a+b
print a['key'] 3
key1
最後說一下類型物件的類型。對象的型別也是一個對象,那麼這個對象的型別又是什麼呢?首先可以確定他也是一個對象。我們稱之為類型的類型。這個十分、非常、非常、very much重要,就是原始碼中的PyType_Type結構體,這個在objects資料夾的typeobject.c檔案裡,原始碼如下:
PyTypeObject PyType_Type = { type", /* tp_name */
sizeof(PyHeapTypeObject), /* tp_basicsize */
sizeof(PyMemberDef), /* tp_itemsize */
(destructor)type_dealloc, /* tp_dealloc */
0, /* tp_print */
0, 0, /* tp_setattr */
0, /* tp_compare */
(reprfunc) type_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)_Py_HashPointer, /* tp_hash */ /* tp_call */
0, */
(getattrofunc)type_getattro, /* tp_getattro */
tp _塞塔特羅*/
0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS, /* tp_flags */
type_doc, /* tp_doc */
(traverseproc)type_traverse, /* t verse */
(查詢)type_clear, /* tp_clear */
type_richcompare, /* tp_richcompare */
偏移量(PyTypeObject , tp_weaklist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
type_methods, /* tp_members */
type_getsets, getset */
0, /* tp_descr_get */
/* tp_descr_get */
0, /* tp_descr_set */
offsetof(PyTypeObject, tp_dict), /* tp_dic /* tp_alloc */
type_new,
PyObject_GC_Del,
(查詢)type_is_gc, /* tp_is_gc */
};
呵呵,這個看起來很複雜,PyInt_Type 和PyType_Type 之間是如何聯繫起來的? 1.32 .09