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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Python進階之“屬性(property)”詳解Python
- display屬性詳解
- cookie屬性詳解Cookie
- CSS字型屬性和文字屬性詳解CSS
- CSS定位屬性詳解CSS
- background屬性用法詳解
- UITableView 屬性用法詳解UIView
- css display屬性詳解CSS
- HTML——② HTML 元素、屬性詳解HTML
- z-index屬性詳解Index
- Android屬性動畫詳解(一),屬性動畫基本用法Android動畫
- After Effects 圖層屬性及屬性組結構詳解
- 屬性配置檔案詳解(2)
- Flutter GetX Tag 屬性使用詳解Flutter
- Rust中的derive屬性詳解Rust
- display的flex屬性使用詳解Flex
- hibernateid屬性generatorclass=””詳解
- Android 佈局屬性詳解Android
- Android taskAffinity屬性使用詳解Android
- PB TreeView 屬性,事件詳解(轉)View事件
- css3中transition屬性詳解CSSS3
- Meta http-equiv屬性詳解(轉)HTTPUI
- Flutter 入門 — Container 屬性詳解FlutterAI
- fill-opacity屬性用法詳解
- iOS- 詳解文字屬性AttributesiOS
- Android圖文詳解屬性動畫Android動畫
- npm package.json屬性詳解NPMPackageJSON
- 【轉】android佈局屬性詳解Android
- Vue — 計算屬性(computed)詳解Vue
- JS 陣列(Arrey)屬性以及方法詳解JS陣列
- vue計算屬性詳解——小白速會Vue
- logstash-input-file 配置屬性詳解
- CSS border-width屬性用法詳解CSS
- CSS3的content屬性詳解CSSS3
- Android中visibility屬性詳解Android
- Android---Android:windowSoftInputMode屬性詳解AndroidWindows
- 應用程式池屬性詳解及配置
- __slots__