日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

[转载] python __slots__ 详解(上篇)

發布時間:2025/3/11 python 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转载] python __slots__ 详解(上篇) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

參考鏈接: Python的__name __(特殊變量)

python中的new-style class要求繼承Python中的一個內建類型,

一般繼承object,也可以繼承list或者dict等其他的內建類型。

?在python新式類中,可以定義一個變量__slots__,它的作用是阻止在實例化類時為實例分配dict,

?

默認情況下每個類都會有一個dict,通過__dict__訪問,這個dict維護了這個實例的所有屬性,舉例如下:?

?

class base(object):

? ? var=9 #類變量

? ? def __init__(self):

? ? ? ? pass

?

b=base()

print b.__dict__

b.x=2 #添加實例變量

print b.__dict__運行結果:

?{ }

?{'x': 2}

?可見:實例的dict只保持實例的變量,對于類的屬性是不保存的,類的屬性包括變量和函數。

?由于每次實例化一個類都要分配一個新的dict,因此存在空間的浪費,因此有了__slots__。

?__slots__是一個元組,包括了當前能訪問到的屬性。

?當定義了slots后,slots中定義的變量變成了類的描述符,相當于java,c++中的成員變量聲明,

?類的實例只能擁有slots中定義的變量,不能再增加新的變量。注意:定義了slots后,就不再有dict。如下:?

?

?

class base(object):

? ? __slots__=('x')

? ? var=8

? ? def __init__(self):

? ? ? ? pass

?

b=base()

b.x=88 #添加實例變量

print b.x

#b.y=99 #無法添加slots之外的變量 (AttributeError: 'base' object has no attribute 'y')

#print b.__dict__ #定義了__slots__后,就不再有__dict__ (AttributeError: 'base' object has no attribute '__dict__')運行結果:

?88

?如果類變量與slots中的變量同名,則該變量被設置為

readonly!!!如下:?

?

?

class base(object):

? ? __slots__=('y')

? ? y=22 # y是類變量,y與__slots__中的變量同名

? ? var=11

? ? def __init__(self):

? ? ? ? pass

? ??

b=base()

print b.y

print base.y

#b.y=66 #AttributeError: 'base' object attribute 'y' is read-only運行結果:

?22

?22

?Python是一門動態語言,可以在運行過程中,修改實例的屬性和增刪方法。一般,任何類的實例包含一個字典__dict__,

?Python通過這個字典可以將任意屬性綁定到實例上。有時候我們只想使用固定的屬性,而不想任意綁定屬性,

?這時候我們可以定義一個屬性名稱集合,只有在這個集合里的名稱才可以綁定。__slots__就是完成這個功能的。?

?

?

class test_slots(object):

? ? __slots__='x','y'

? ? def printHello(self):

? ? ? ? print 'hello!'

?

class test(object):

? ? def printHello(self):

? ? ? ? print 'hello'

?

print dir(test_slots) #可以看到test_slots類結構里面包含__slots__,x,y

print dir(test)#test類結構里包含__dict__

print '**************************************'

ts=test_slots()

t=test()

print dir(ts) #可以看到ts實例結構里面包含__slots__,x,y,不能任意綁定屬性

print dir(t) #t實例結構里包含__dict__,可以任意綁定屬性

print '***************************************'

ts.x=11 #只能綁定__slots__名稱集合里的屬性

t.x=12 #可以任意綁定屬性

print ts.x,t.x

ts.y=22 #只能綁定__slots__名稱集合里的屬性

t.y=23? #可以任意綁定屬性

print ts.y,t.y

#ts.z=33 #無法綁定__slots__集合之外的屬性(AttributeError: 'test_slots' object has no attribute 'z')

t.z=34 #可以任意綁定屬性

print t.z 運行結果:

?['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '

__slots__', '__str__', '__subclasshook__', 'printHello', '

x', 'y']

?['__class__', '__delattr__', '

__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'printHello']

?**************************************

?['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '

__slots__', '__str__', '__subclasshook__', 'printHello', '

x', 'y']

?['__class__', '__delattr__', '

__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'printHello']

?***************************************

?11 12

?22 23

?34

?

?正如上面所說的,默認情況下,Python的新式類和經典類的實例都有一個

dict來存儲實例的屬性。這在一般情況下還不錯,而且非常靈活,

?乃至在程序中可以

隨意設置新的屬性。但是,對一些在”編譯”前就知道有幾個固定屬性的小class來說,這個dict就有點浪費內存了。

?當需要創建大量實例的時候,這個問題變得尤為突出。一種解決方法是在

新式類中定義一個__slots__屬性。

?__slots__聲明中包含若干實例變量,并為每個實例預留恰好足夠的空間來保存每個變量;這樣Python就不會再使用dict,從而節省空間。

?

【使用memory_profiler模塊,memory_profiler模塊是在逐行的基礎上,測量代碼的內存使用率。盡管如此,它可能使得你的代碼運行的更慢。使用裝飾器@profile來標記哪個函數被跟蹤。】 下面,我們看一個例子:

from? memory_profiler import profile

class A(object): #沒有定義__slots__屬性

? ? def __init__(self,x):

? ? ? ? self.x=x

?

@profile

def main():

? ? f=[A(523825) for i in range(100000)]

?

if __name__=='__main__':

? ? main()運行結果,如下圖:

?

?

?第2列表示該行執行后Python解釋器的內存使用情況,

第3列表示該行代碼執行前后的內存變化。

?在沒有定義__slots__屬性的情況下,該代碼共使用了20.8MiB內存。

?從結果可以看出,內存使用是以MiB為單位衡量的,表示的mebibyte(1MiB = 1.05MB)

from? memory_profiler import profile

class A(object):#定義了__slots__屬性

? ? __slots__=('x')

? ? def __init__(self,x):

? ? ? ? self.x=x

?

@profile

def main():

? ? f=[A(523825) for i in range(100000)]

?

if __name__=='__main__':

? ? main()運行結果,如下圖:

?

?

?可以看到,在定義了__slots__屬性的情況下,該代碼共使用了6.1MiB內存,比上面的20.8MiB節省了很多內存!

?綜上所述,在確定了

類的屬性固定的情況下,可以

使用__slots__來優化內存。

?提醒:不要貿然進行這個優化,把它用在所有地方。這種做法不利于代碼維護,而且只有生成數以千計的實例的時候才會有明顯效果。

?

?(完)

總結

以上是生活随笔為你收集整理的[转载] python __slots__ 详解(上篇)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。