淺談__slots__


__slots__在python中是扮演屬性聲明(Attribute Declaration)的角色,當然屬性本身不用聲明,只需要在使用前賦值即可,但是實際上,屬性的應用遠非在使用前賦值就行,所以有attribute declaration, attribute accessor,attribute management 等概念,本文對__slots__屬性聲明做一個學習總結,其他的之后會陸續總結。

(1)Why __slots__?

__slots__用來限制類的實例的屬性,優化內存(為每個實例都分配命名空間,如果很多實例被建立起來,然而需要較少的屬性,就會很浪費內存空間,所以,python對每個slot 屬性在每個實例中都保留了足夠空間),防止出現碼字錯誤(typos)等。

但是,它也打破了python核心的動態性質,比如,任何命名通過賦值就可以創建,因此它們應當在非常清楚的真的需要的時候使用,引用python 手冊的原話:

Best reserved for rare cases where there are large numbers of instances in a memory-critical application.

(2)__slots__基本用法

__slots__用在新類型類中(New-Style class)是類屬性,為列表,其中包含了該類實例的屬性,類實例化后,僅允許創建在__slots__列表中的屬性,如果定義的屬性不在其中,則拋出AttributeError異常。以下代碼簡單的展示了其基本用法:

>>> class c:
    __slots__=['a','b']

    
>>> x=c()
>>> x.a
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    x.a
AttributeError: a
>>> x.a=1
>>> x.b=2
>>> x.a,x.b
(1, 2)
>>> x.c=8
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    x.c=8
AttributeError: 'c' object has no attribute 'c'

(3)注意事項

(a)__slots__與命名空間字典__dict__

有slots的實例,有些根本就沒有__dict__屬性,有些實例的屬性不在__dict__中。接上面代碼,繼續...

>>> x.__dict__
Traceback (most recent call last):
  File "<pyshell#9>", line 1, in <module>
    x.__dict__
AttributeError: 'c' object has no attribute '__dict__'

而沒有命名空間字典(namespace dictionary)__dict__,就意味着不可能為實例創建一個不在slots中的屬性,怎么辦?可以通過把__dict__也寫到__slots__中來解決。

>>> class c:
    __slots__=['a','b','__dict__']

    
>>> x=c()
>>> x.a=1;x.b=2;x.c=3
>>> x.a,x.b,x.c
(1, 2, 3)
>>> x.__dict__
{'c': 3}

可以看到可以創建一個x.c,而c不在slots中,在__dict__中。而getattr方法可以對slots中的屬性進行訪問。接上面代碼:

>>> getattr(x,'a');getattr(x,'b')
1
2

(b)在超類(superclass)中的多重__slot__

__slots__是一個類屬性,所以子類的slots會繼承父類的slots。

>>> class E:
    __slots__=['c','d']

    
>>> class D(E):
    __slots__=['a','__dict__']

    
>>> x=D()
>>> x.a=1;x.c=2;x.d=3;x.e=8
>>> x.a,x.d,x.c,x.e
(1, 3, 2, 8)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM