__slots__ 是python的壹大神器。
它有兩大的特點:
python文檔中這樣介紹它
首先第壹點,python的動態性壹部分源自於 __dict__ ,屬性都保存在 __dict__ 的壹個字典中,我們可以隨時向這個字典添加新內容,這是 MonkeyPatch 的能力。
而當我們顯示的聲明了 __slots__ ,python將不會給這個類創建 __dict__ 和 __weakref__
沒有了 __dict__ 我們便不能隨意創建實例屬性,而必須遵守 __slots__ 的約定。
對於性能而言,使用了 __slots__ 後,屬性會直接存儲到對象中,而不是 __dict__ 中,相當於少了壹次檢索步驟。
__slots__ 的兩大優點,對於python來說,是難以拒絕的誘惑。既能限制不必要的動態性,又能提高性能!
但是 __slots__ 遇到繼承時,就會出現很多問題。準確的說, __slots__ 不會被繼承。當我們用壹個不帶有 __slots__ 的子類,繼承帶有 __slots__ 的父類時。子類還是會生成 __dict__ 和 __weakref__ 。
這是之前寫的壹個metaclass,創建新的類對象時,會進行以下邏輯。
實際上我們的目的正是解決,父類規定的 __slots__ 約束不了無 __slots__ 子類的問題。這個結果令人非常滿意
註意這裏子類的d,在 pycharm 等IDE中不會提示錯誤,因為 pycharm 無法探知妳的metaclass做了這樣 逆天改命 的邏輯。
需要註意壹點, __slots__ 是 類對實例屬性的約束 ,而類對象無法通過該屬性,約束自己。即為類對象添加新屬性,仍然是被允許的。
按照正常思路,也許我們應該到metaclass寫壹個 __slots__ ,但實際上這是不被允許的。
抽空找時間我會考慮下有無可行性。