Python - __slots__屬性詳解
簡介
__slots__
允許我們宣告並限定類成員,並拒絕類建立__dict__
和__weakref__
屬性以節約記憶體空間。
Python是動態語言,對於普通的類,可以為類例項賦值任何屬性,這些屬性會儲存在__dict__
中:
>>> class Student(object):... pass... >>> Abey = Student()>>> Abey.name = 'Abey'>>> Abey.__dict__ {'name': 'Abey'}
這樣的特性帶來兩個問題:
資料透過字典(Hash)儲存所佔用的空間較大
如何禁止隨意生成類屬性
當然,__slots__
就能解決這兩個問題。透過__slots__
屬性限定類屬性的建立:
>>> class Student(object):... __slots__ = ('name', 'age') ... >>> Abey = Student()>>> Abey.name = 'Abey'>>> Abey.gender = 'Female'Traceback (most recent call last): File "<input>", line 1, in <module>AttributeError: 'Student' object has no attribute 'gender'>>> Abey.__dict__Traceback (most recent call last): File "<input>", line 1, in <module>AttributeError: 'Student' object has no attribute '__dict__'
可以看到,在定義了__slots__
變數後,Student類例項已經不能隨意建立不在__slots__
定義內的屬性gender,同時例項中也不再有__dict__
結構。
用法
繼承樹
__slots__
在繼承中有兩種表現:
子類未宣告
__slots__
時,不繼承父類的__slots__
,即此時子類例項可以隨意賦值屬性子類宣告
__slots__
時,繼承父類的__slots__
,即此時子類的__slots__
為其自身+父類的__slots__
以下面的父類為例:
>>> class Student(object):... __slots__ = ('name', 'age')...
建立一個子類不宣告__slots__
,該類例項可以建立父類__slots__
限定之外的屬性gender:
>>> class SubStudent(Student):... pass... >>> Bob = SubStudent()>>> Bob.gender = 'Male'>>> Bob.__dict__ {'gender': 'Male'}
而建立一個宣告__slots__
的子類,該類屬性則只能建立父類__slots__
+自身__slots__
限定的屬性:
>>> class SubStudent2(Student):... __slots__ = 'gender'... >>> Cathy = SubStudent2()>>> Cathy.gender = 'Female'>>> Cathy.name = 'Cathy'>>> Cathy.teacher = 'Mrs. Wang'Traceback (most recent call last): File "<input>", line 1, in <module>AttributeError: 'SubStudent2' object has no attribute 'teacher'
注意:子類的__slots__
本身已經繼承自父類,無需重複宣告父類已宣告的屬性。例如上例,重複宣告會多佔用記憶體空間:
>>> class SubStudent3(Student):... __slots__ = ('name', 'age', 'gender')... >>> from sys import getsizeof>>> getsizeof(Student()), getsizeof(SubStudent2()), getsizeof(SubStudent3()) (56, 64, 80)
效能對比
我們為什麼要使用__slots__
呢?
更快速地賦值屬性
參考Stack Overflow回答中給出的資料:
import timeitclass Foo(object): __slots__ = 'foo',class Bar(object): passslotted = Foo() not_slotted = Bar()def get_set_delete_fn(obj): def get_set_delete(): obj.foo = 'foo' obj.foo del obj.foo return get_set_delete
得到測試結果為:
>>> min(timeit.repeat(get_set_delete_fn(slotted)))0.2846834529991611>>> min(timeit.repeat(get_set_delete_fn(not_slotted)))0.3664822799983085
可以看到,在相同的環境(Ubuntu)下,slots為Python3.5帶來了接近30%的賦值速度提升:
>>> 0.3664822799983085 / 0.28468345299916111.2873325658284342
節約記憶體空間
由於不使用__dict__
儲存物件的屬性,__slots__
在一些場景下能夠節約極大的記憶體空間。具體資料可以檢視參考中的回答連結,不贅述。
作者:嚴北
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4301/viewspace-2818822/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- display屬性詳解
- CSS字型屬性和文字屬性詳解CSS
- CSS定位屬性詳解CSS
- HTML——② HTML 元素、屬性詳解HTML
- z-index屬性詳解Index
- After Effects 圖層屬性及屬性組結構詳解
- Flutter 入門 — Container 屬性詳解FlutterAI
- display的flex屬性使用詳解Flex
- Vue — 計算屬性(computed)詳解Vue
- Flutter GetX Tag 屬性使用詳解Flutter
- 屬性配置檔案詳解(2)
- Rust中的derive屬性詳解Rust
- css3中transition屬性詳解CSSS3
- JS 陣列(Arrey)屬性以及方法詳解JS陣列
- border-sizing屬性詳解和應用
- css box-sizing屬性值詳解(MDN)CSS
- vue計算屬性詳解——小白速會Vue
- 提高班1:ImageView中ScaleType屬性詳解,配圖詳解View
- Python - 使用__slots__節省空間Python
- Python 類的屬性與例項屬性Python
- python物件屬性管理(2):property管理屬性Python物件
- __slots__
- CSS中position屬性( absolute | relative | static | fixed )詳解CSS
- 前端進階課程之物件屬性特性詳解前端物件
- Vue之computed(計算屬性)詳解get()、set()Vue
- 好程式設計師分享placeholder屬性詳解程式設計師
- script標籤的defer和async屬性詳解
- PDO 中的ATTR_EMULATE_PREPARES屬性詳解
- Vue路由物件屬性 .meta $route.matched詳解Vue路由物件
- Python中的屬性Python
- Python - 物件導向程式設計 - 公共屬性、保護屬性、私有屬性Python物件程式設計
- iOS 開發:『Runtime』詳解(四)獲取類詳細屬性、方法iOS
- CSS - 定位屬性position使用詳解(static、relative、fixed、absolute)CSS
- Kotlin——中級篇(二): 屬性與欄位詳解Kotlin
- 裝備屬性欄位設計和投放詳解
- css詳解position五種屬性用法及其含義CSS
- css詳解background八大屬性及其含義CSS
- Python列印類的屬性Python