溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

__slots__關(guān)鍵字究竟是做什么的呢

發(fā)布時(shí)間:2020-07-02 11:46:14 來源:億速云 閱讀:159 作者:清晨 欄目:編程語(yǔ)言

這篇文章將為大家詳細(xì)講解有關(guān)__slots__關(guān)鍵字究竟是做什么的呢,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

如果你看過github當(dāng)中一些大牛的代碼,你會(huì)發(fā)現(xiàn)很多大牛經(jīng)常在類的頂部加上__slots__關(guān)鍵字。如果你足夠好奇,你可能會(huì)試著把這個(gè)關(guān)鍵字去掉再運(yùn)行試試,你會(huì)發(fā)現(xiàn)去掉了之后什么也沒有發(fā)生,一切依然運(yùn)行得很好。

那么這個(gè)__slots__關(guān)鍵字究竟是做什么的呢?

它主要有兩個(gè)功能,我們先來說第一個(gè)功能,就是限制用戶的使用。

我們都知道Python是一門非常靈活的動(dòng)態(tài)語(yǔ)言,很多在其他語(yǔ)言看起來完全不能容忍的事情在Python當(dāng)中是可行的,這也是Python的設(shè)計(jì)理念,為了靈活和代碼方便犧牲了效率。比如我們來看一個(gè)很簡(jiǎn)單的例子,由于Python是動(dòng)態(tài)語(yǔ)言,所以類的成員甚至可以在類創(chuàng)建好了之后動(dòng)態(tài)創(chuàng)建。這在靜態(tài)語(yǔ)言當(dāng)中是絕對(duì)不行的,我們只能調(diào)用類當(dāng)中已有的屬性,是不能或者很難添加新屬性的。

比如這段代碼:

class Exp:
    def __init__(self):
        self.a = None
        self.b = None


if __name__ == "__main__":
    exp = Exp()
    exp.c = 3
    print(exp.c)

我們定義了一個(gè)類叫做Exp,我們?yōu)樗鼊?chuàng)建了a和b兩個(gè)成員。但是我們?cè)谑褂玫臅r(shí)候,對(duì)c成員進(jìn)行了賦值。要知道Exp類當(dāng)中是沒有成員c的,但是程序并不會(huì)報(bào)錯(cuò),我們這么運(yùn)行了之后它會(huì)將c添加進(jìn)這個(gè)實(shí)例當(dāng)中。

從一方面來看,這當(dāng)然非常靈活,但是另一方面,這也留下了隱患。如果用戶隨意添加屬性,可能會(huì)導(dǎo)致未知的問題,尤其在復(fù)雜的系統(tǒng)當(dāng)中。所以有些時(shí)候?yàn)榱藝?yán)謹(jǐn),我們會(huì)不希望用戶做這種動(dòng)態(tài)的修改。__slots__正是用來做這個(gè)的。

我們把這個(gè)關(guān)鍵字加上,再來運(yùn)行結(jié)果就不一樣了:

class Exp:

    __slots__ = ['a', 'b']
    def __init__(self):
        self.a = None
        self.b = None


if __name__ == "__main__":
    exp = Exp()
    exp.c = 3
    print(exp.c)

如果你運(yùn)行這段代碼的話,你會(huì)得到一個(gè)報(bào)錯(cuò),提示你Exp這個(gè)對(duì)象當(dāng)中并沒有c這個(gè)成員,也就是說我們只能運(yùn)用__slots__這個(gè)關(guān)鍵字當(dāng)中定義的成員,對(duì)于沒有定義的成員不能隨意創(chuàng)建,這樣就限制了用戶的使用。

雖然現(xiàn)在大部分人使用這個(gè)關(guān)鍵字都是報(bào)著這個(gè)目的,但是很遺憾的是,Python創(chuàng)建者的初衷其實(shí)并不是這個(gè)。這就談到了__slots__關(guān)鍵字的第二個(gè)作用,就是節(jié)省內(nèi)存。

如果了解過Python底層的實(shí)現(xiàn)原理,你會(huì)發(fā)現(xiàn)在Python當(dāng)中為每一個(gè)實(shí)例都創(chuàng)建了一個(gè)字典,就是大名鼎鼎的__dict__字典。正是因?yàn)楸澈笥幸粋€(gè)字典,所以我們才可以創(chuàng)造出原本不存在的成員,也才支持這樣動(dòng)態(tài)的效果。我們可以人工地調(diào)用這個(gè)字典輸出其中的內(nèi)容,我們?cè)诩由蟔_slots__關(guān)鍵字之前,輸出的結(jié)果是這樣的:

{'a': None, 'b': None}

但是加上了這個(gè)關(guān)鍵字之后,會(huì)得到一個(gè)報(bào)錯(cuò),會(huì)告訴你Exp這個(gè)對(duì)象當(dāng)中沒有__dict__這個(gè)成員。原因很簡(jiǎn)單,因?yàn)槭褂胐ict來維護(hù)實(shí)例,會(huì)消耗大量的內(nèi)存,額外存儲(chǔ)了許多數(shù)據(jù),而使用__slots__之后,Python內(nèi)部將不再為實(shí)例創(chuàng)建一個(gè)字典來維護(hù),而是會(huì)使用一個(gè)固定大小的數(shù)組,這樣就節(jié)省了大量的空間。

這個(gè)節(jié)省可不是一點(diǎn)半點(diǎn),一般可以節(jié)省一半以上。也就是說犧牲了一定的靈活性,保證了性能。這一點(diǎn)也是__slots__這個(gè)關(guān)鍵字設(shè)計(jì)的初衷,但是現(xiàn)在很多人都用錯(cuò)了地方。


關(guān)于__slots__關(guān)鍵字究竟是做什么的呢就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI