Python源碼剖析筆記1——Python對(duì)象初見(jiàn)

工作整兩年了遗座,用python最多馋记,然而對(duì)于python內(nèi)部機(jī)制不一定都清楚,每天沉醉于增刪改查的簡(jiǎn)單邏輯編寫(xiě),實(shí)在耗神。很多東西不用就忘記了,比如C語(yǔ)言驾茴,正好,python源碼用C寫(xiě)的,分析python源碼的同時(shí)又能溫故C語(yǔ)言基礎(chǔ),實(shí)在是件很好的事情。另外,還有陳儒大神的《python源碼剖析》做指引挥转,分析也不至于沒(méi)頭沒(méi)腦。期望在一個(gè)月的業(yè)余時(shí)間豁护,能有所小成班缎,以此為記沉唠。

1 python中的對(duì)象

python中乳蛾,一切東西都是對(duì)象因惭,在c語(yǔ)言實(shí)現(xiàn)中對(duì)應(yīng)著結(jié)構(gòu)體。首先當(dāng)然還是從python內(nèi)建對(duì)象開(kāi)始看起,最基本的是PyIntObject, PyStringObject, PyListObject, PyDictObject這幾個(gè)讳推,他們分別屬于int,string, list, dict類(lèi)型设拟。從python2.2之后有了new style class之后帘撰,這些內(nèi)置對(duì)象都是繼承自object類(lèi)型核行,object在代碼中對(duì)應(yīng)PyBaseObject_Type惩系。比如我們賦值語(yǔ)句a=3擦剑,那么a就是一個(gè)PyIntObject對(duì)象,它的類(lèi)型是int,在代碼中對(duì)應(yīng)PyInt_Type炫乓,PyInt_Type也是一種對(duì)象末捣,我們稱(chēng)之為類(lèi)型對(duì)象侠姑。那么PyInt_Type它的類(lèi)型是什么呢,答案是type箩做, 對(duì)應(yīng)到代碼中就是PyType_Type莽红。當(dāng)然object也是一個(gè)類(lèi)型對(duì)象,它的類(lèi)型也是PyType_Type邦邦。這么一層層下去安吁,PyType_Type也是個(gè)對(duì)象,那它的類(lèi)型又是什么呢燃辖,沒(méi)錯(cuò)鬼店,答案就是它的類(lèi)型就是它自己,黔龟「局牵看下面的驗(yàn)證代碼:

##內(nèi)建對(duì)象測(cè)試
In [1]: a = 3

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

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

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

In [5]: int.__base__
Out[5]: object

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

先分析下幾個(gè)基礎(chǔ)內(nèi)建對(duì)象在C語(yǔ)言中的結(jié)構(gòu)體以及常用的幾個(gè)宏确沸,為了方便,我用的也是陳儒大神分析的那個(gè)版本一致俘陷,版本是2.5.6.源碼官網(wǎng)有下載罗捎。

// 內(nèi)建對(duì)象基礎(chǔ)
#define PyObject_HEAD                   \
        Py_ssize_t ob_refcnt;           \
        struct _typeobject *ob_type;

#define PyObject_HEAD_INIT(type)        \
        1, type,

#define PyObject_VAR_HEAD               \
        PyObject_HEAD                   \
        Py_ssize_t ob_size; /* Number of items in variable part */
#define Py_INVALID_SIZE (Py_ssize_t)-1

typedef struct _object {
        PyObject_HEAD
} PyObject;

typedef struct {
        PyObject_VAR_HEAD
} PyVarObject;

typedef struct _typeobject {
        PyObject_VAR_HEAD
        const char *tp_name; /* For printing, in format "<module>.<name>" */
        Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */
        destructor tp_dealloc;
        printfunc tp_print;
        getattrfunc tp_getattr;
        setattrfunc tp_setattr;
        cmpfunc tp_compare;
        reprfunc tp_repr;
        ...
} PyTypeObject;

typedef struct {
    PyObject_HEAD
    long ob_ival;
} PyIntObject;

typedef struct {
    PyObject_VAR_HEAD
    long ob_shash;
    int ob_sstate;
    char ob_sval[1];
    /* Invariants:
     *     ob_sval contains space for 'ob_size+1' elements.
     *     ob_sval[ob_size] == 0.
     *     ob_shash is the hash of the string or -1 if not computed yet.
     *     ob_sstate != 0 iff the string object is in stringobject.c's
     *       'interned' dictionary; in this case the two references
     *       from 'interned' to this object are *not counted* in ob_refcnt.
     */
} PyStringObject;

如代碼中所示,PyObject是所有Python對(duì)象的基石拉盾,所有后續(xù)看到的對(duì)象都有一個(gè)相同的PyObject頭部,從而我們可以在源碼中看到所有的對(duì)象都可以用PyObject指針指向桨菜,這就是面向?qū)ο笾薪?jīng)常用到的多態(tài)的技巧了。Python內(nèi)部各個(gè)函數(shù)對(duì)象間也是通過(guò)PyObject傳遞捉偏,即便本身這是一個(gè)PyIntObject類(lèi)型的對(duì)象倒得,代碼中并不會(huì)用PyIntObject*指針進(jìn)行傳遞,這也是為了實(shí)現(xiàn)多態(tài)夭禽。比如下面的函數(shù):

void Print(PyObject* object) {
    object->ob_type->tp_print(object);
}

另外如代碼中注釋所說(shuō)的霞掺,變長(zhǎng)對(duì)象的ob_size指的是元素個(gè)數(shù),不是字節(jié)數(shù)目讹躯。

2 python對(duì)象引用計(jì)數(shù)

下面是幾個(gè)常用的操作對(duì)象引用計(jì)數(shù)的宏定義(object.h)菩彬,一并列出,這里去除了一些調(diào)試時(shí)用的代碼潮梯,更容易看明白代碼含義骗灶。Py_NewReference是初始化時(shí)對(duì)象時(shí)設(shè)置引用計(jì)數(shù), Py_INCREF和Py_DECREF分別用來(lái)增加引用技術(shù)和減少引用計(jì)數(shù)。從代碼中可以看到秉馏,python增加引用和減少引用都是通過(guò)這些宏操作的耙旦,**有一點(diǎn)需要注意的是,當(dāng)對(duì)象引用ob_refcnt減小到0時(shí)萝究,會(huì)調(diào)用對(duì)象的析構(gòu)函數(shù)免都,析構(gòu)函數(shù)并不一定會(huì)調(diào)用free釋放內(nèi)存空間,因?yàn)轭l繁申請(qǐng)和釋放內(nèi)存嚴(yán)重影響性能帆竹,所以在后面看到python有大量用到內(nèi)存池技術(shù)绕娘,對(duì)提升性能有很大效果。

需要說(shuō)明的是馆揉,類(lèi)型對(duì)象是不在引用計(jì)數(shù)規(guī)則之中的业舍,每個(gè)對(duì)象指向類(lèi)型對(duì)象的指針并不視為類(lèi)型對(duì)象的引用,也就是說(shuō)不會(huì)影響類(lèi)型對(duì)象的引用計(jì)數(shù)升酣,類(lèi)型對(duì)象永遠(yuǎn)不會(huì)被析構(gòu)舷暮。

#define _Py_NewReference(op) ((op)->ob_refcnt = 1)


#define _Py_Dealloc(op) (*(op)->ob_type->tp_dealloc)((PyObject *)(op)))

#define Py_INCREF(op) ((op)->ob_refcnt++)

#define Py_DECREF(op)                                   \
        if (--(op)->ob_refcnt != 0)                     \
            ;
        else                                            \
            _Py_Dealloc((PyObject *)(op))
            
#define Py_CLEAR(op)                            \
        do {                                    \
                if (op) {                       \
                        PyObject *tmp = (PyObject *)(op);       \
                        (op) = NULL;            \
                        Py_DECREF(tmp);         \
                }                               \
        } while (0)

/* Macros to use in case the object pointer may be NULL: */
#define Py_XINCREF(op) if ((op) == NULL) ; else Py_INCREF(op)
#define Py_XDECREF(op) if ((op) == NULL) ; else Py_DECREF(op)

3 Python對(duì)象分類(lèi)

python中的對(duì)象大致可以分為下面幾類(lèi):

  • 數(shù)值對(duì)象:如integer,float,boolean
  • 序列集合對(duì)象:如string,list,tuple
  • 字典對(duì)象:如dict
  • 類(lèi)型對(duì)象:如type
  • 內(nèi)部對(duì)象:如后面會(huì)看到的code,function噩茄,frame下面,module以及method對(duì)象等。

4 參考資料

  • 《python源碼剖析》
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末绩聘,一起剝皮案震驚了整個(gè)濱河市沥割,隨后出現(xiàn)的幾起案子耗啦,更是在濱河造成了極大的恐慌,老刑警劉巖机杜,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帜讲,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡椒拗,警方通過(guò)查閱死者的電腦和手機(jī)似将,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蚀苛,“玉大人在验,你說(shuō)我怎么就攤上這事《挛矗” “怎么了腋舌?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)渗蟹。 經(jīng)常有香客問(wèn)我块饺,道長(zhǎng),這世上最難降的妖魔是什么拙徽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任刨沦,我火速辦了婚禮,結(jié)果婚禮上膘怕,老公的妹妹穿的比我還像新娘。我一直安慰自己召庞,他們只是感情好岛心,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著篮灼,像睡著了一般忘古。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上诅诱,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天髓堪,我揣著相機(jī)與錄音,去河邊找鬼娘荡。 笑死干旁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的炮沐。 我是一名探鬼主播争群,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼大年!你這毒婦竟也來(lái)了换薄?” 一聲冷哼從身側(cè)響起玉雾,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎轻要,沒(méi)想到半個(gè)月后复旬,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冲泥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年驹碍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柏蘑。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡幸冻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出咳焚,到底是詐尸還是另有隱情洽损,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布革半,位于F島的核電站碑定,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏又官。R本人自食惡果不足惜延刘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望六敬。 院中可真熱鬧碘赖,春花似錦、人聲如沸外构。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)审编。三九已至撼班,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間垒酬,已是汗流浹背砰嘁。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留勘究,地道東北人矮湘。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像乱顾,于是被迫代替她去往敵國(guó)和親板祝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1.元類(lèi) 1.1.1類(lèi)也是對(duì)象 在大多數(shù)編程語(yǔ)言中走净,類(lèi)就是一組用來(lái)描述如何生成一個(gè)對(duì)象的代碼段券时。在Python中這...
    TENG書(shū)閱讀 1,253評(píng)論 0 3
  • C++調(diào)用python 在C/C++中嵌入Python孤里,可以使用Python提供的強(qiáng)大功能,通過(guò)嵌入Python可...
    Bruce_Szh閱讀 13,769評(píng)論 1 7
  • http://python.jobbole.com/85231/ 關(guān)于專(zhuān)業(yè)技能寫(xiě)完項(xiàng)目接著寫(xiě)寫(xiě)一名3年工作經(jīng)驗(yàn)的J...
    燕京博士閱讀 7,548評(píng)論 1 118
  • 兩本不錯(cuò)的書(shū): 《Python參考手冊(cè)》:對(duì)Python各個(gè)標(biāo)準(zhǔn)模塊橘洞,特性介紹的比較詳細(xì)捌袜。 《Python核心編程...
    靜熙老師哈哈哈閱讀 3,359評(píng)論 0 80
  • “丙申年臘月初,深冬極寒炸枣,有感于斯人虏等,故作此闕∈食Γ” 怨思長(zhǎng)霍衫,兩地相望,一處凄涼侯养。夢(mèng)回凝語(yǔ)淚私藏敦跌,誰(shuí)...
    永生的王爵閱讀 359評(píng)論 3 3