python __slots__ 與實例屬性的關聯性
本文深入探討 Python 中 __slots__ 的用法,以及修改類屬性為何會影響實例屬性,特別是當實例已擁有該屬性時。
讓我們先看一段代碼:
class Person: __slots__ = ("name",) # 注意這里加了逗號,變成tuple def __init__(self): self.name = 13 shili = Person() print(shili.name) # 輸出 13 print(id(shili.name), id(Person.name)) # 輸出 shili.name 和 Person.name 的內存地址 Person.name = 143 print(id(shili.name), id(Person.name)) # 輸出 shili.name 和 Person.name 的內存地址,兩者相同 shili.name = 13 print(shili.name) # 輸出 13
這段代碼定義了 Person 類,并使用 __slots__ 限制實例屬性為 “name”。 初始化實例 shili 時,我們為其設置了 name 屬性。 值得注意的是,即使 shili 已經擁有自己的 name 屬性,修改類屬性 Person.name 后,shili.name 的值也會隨之變化。 這并非實例屬性繼承或優先級問題,而是由于 __slots__ 的工作機制。
立即學習“Python免費學習筆記(深入)”;
__slots__ 限制了實例可擁有的屬性,但它并沒有阻止實例屬性指向類屬性。 當創建 shili 實例并賦值 self.name = 13 時,Python 并沒有為 shili 創建新的 name 屬性,而是讓 shili.name 指向了類屬性 Person.name。 因此,修改 Person.name 時,shili.name 也指向了新的內存地址,從而改變了它的值。 第一次打印 id(shili.name), id(Person.name) 時,兩個 ID 相同,證實了這一點。 只有當 shili.name 被重新賦值后,才為 shili 創建了新的 name 屬性,此時 shili.name 和 Person.name 指向不同的內存地址。
總結:使用 __slots__ 時,需特別注意實例屬性與類屬性的關系。 雖然 __slots__ 限制了實例屬性的創建,但如果實例屬性未被顯式創建,它會指向類屬性,導致修改類屬性會影響實例屬性。 只有當實例屬性被顯式賦值后,實例才擁有獨立的屬性,此時修改類屬性不會再影響實例屬性。