[轉載] 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__來優化內存。

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

?

?(完)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/540543.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/540543.shtml
英文地址,請注明出處:http://en.pswp.cn/news/540543.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

委托BegionInvoke和窗體BegionInvoke

委托BegionInvoke是指通過委托方法執行多線程任務,例如: //定義委托成員變量 delegate void dg_DeleAirport(); //指定委托函數 dg_DeleAirport dga AirportBLL.DeleteHistoryTransAirport; //通過BeginInvoke以異步線程方式執行委托函數,可…

圖論 弦_混亂的弦

圖論 弦Problem statement: 問題陳述: You are provided an input string S and the string "includehelp". You need to figure out all possible subsequences "includehelp" in the string S? Find out the number of ways in which the s…

[轉載] Python列表操作

參考鏈接: Python中的基本運算符 Python列表: 序列是Python中最基本的數據結構。序列中的每個元素都分配一個數字 - 它的位置,或索引,第一個索引是0,第二個索引是1,依此類推; Python有6個序列的…

「原創」從馬云、馬化騰、李彥宏的對話,看出三人智慧差在哪里?

在今年中國IT領袖峰會上,馬云、馬化騰、李彥宏第一次單獨合影,同框畫面可以說很難得了。BAT關心的走勢一直是同行們競相捕捉的熱點,所以三位大Boss在這次大會上關于人工智能的見解,也受到廣泛關注與多方解讀。馬云認為機器比人聰明…

python 注釋含注釋_Python注釋

python 注釋含注釋Python注釋 (Python comments) Comments in Python are used to improve the readability of the code. It is useful information given by the programmer in source code for a better understanding of code and logic that they have used to solve the …

C2的完整形式是什么?

C2:核心2 (C2: Core 2) C2 is an abbreviation of "Core 2" or "Intel Core 2". C2是“ Core 2”或“ Intel Core 2”的縮寫 。 It is a family of Intels processor which was launched on the 27th of July, 2006. It comprises a series of…

scala特性_Scala | 特性應用

scala特性特性應用 (Trait App) Scala uses a trait called "App" which is used to convert objects into feasible programs. This conversion is done using the DelayedInit and the objects are inheriting the trait named App will be using this function. T…

[轉載] Python3中的表達式運算符

參考鏈接: Python中的除法運算符 1:Python常用表達式運算符 yield 生成器函數send協議 lambda args:expression 創建匿名函數 x if y else z 三元選擇表達式(當y為真時,x才會被計算) x or y 邏輯或(僅但x為假時y才會被計算) x and …

字符串矩陣轉換成長字符串_字符串矩陣

字符串矩陣轉換成長字符串Description: 描述: In this article, we are going to see how backtracking can be used to solve following problems? 在本文中,我們將看到如何使用回溯來解決以下問題? Problem statement: 問題陳述&#xf…

pythonchallenge_level2

level2 地址:http://www.pythonchallenge.com/pc/def/ocr.html。 源碼:gitcode.aliyun.com:qianlizhixing12/PythonChallenge.git。 問題:找出頁面源碼一點提示注釋中的稀有字符。 #!/usr/bin/env python3 # -*- coding:UTF-8 -*-# Level 2im…

[轉載] python類運算符的重載

參考鏈接: Python中的運算符重載 alist input().split() blist input().split() n float(input()) class Vector: def __init__(self, x0, y0, z0): # 請在此編寫你的代碼(可刪除pass語句) self.X x self.Y y self.Z z # 代碼結束 def __add__(self, other):…

r語言 運算符_R語言運算符

r語言 運算符R語言中的運算符 (Operators in R Language) Generally speaking, an operator is a symbol that gives proper commands to the compiler regarding a specific action to be executed. The operators are used for carrying out the mathematical or logical cal…

[轉載] Python基礎之類型轉換與算術運算符

參考鏈接: Python中的運算符函數| 1 一、注釋 1.注釋:對程序進行標注和說明,增加程序的可讀性。程序運行的時候會自動忽略注釋。 2.單行注釋:使用#的形式。但是#的形式只能注釋一行,如果有多行,就不方便…

java awt 按鈕響應_Java AWT按鈕

java awt 按鈕響應The Button class is used to implement a GUI push button. It has a label and generates an event, whenever it is clicked. As mentioned in previous sections, it extends the Component class and implements the Accessible interface. Button類用于…

解決“由于應用程序的配置不正確,應用程序未能啟動,重新安裝應用程序可能會糾正這個問題”...

在VS2005下用C寫的程序,在一臺未安裝VS2005的系統上, 用命令行方式運行,提示: “系統無法執行指定的程序” 直接雙擊運行,提示: “由于應用程序的配置不正確,應用程序未能啟動,重新安…

qgis在地圖上畫導航線_在Laravel中的航線

qgis在地圖上畫導航線For further process we need to know something about it, 為了進一步處理,我們需要了解一些有關它的信息, The route is a core part in Laravel because it maps the controller for sending a request which is automatically …

Logistic回歸和SVM的異同

這個問題在最近面試的時候被問了幾次,讓談一下Logistic回歸(以下簡稱LR)和SVM的異同。由于之前沒有對比分析過,而且不知道從哪個角度去分析,一時語塞,只能不知為不知。 現在對這二者做一個對比分析&#xf…

[轉載] python學習筆記2--操作符,數據類型和內置功能

參考鏈接: Python中的Inplace運算符| 1(iadd(),isub(),iconcat()…) 什么是操作符? 簡單的回答可以使用表達式4 5等于9,在這里4和5被稱為操作數,被稱為操符。 Python語言支持操作者有以下幾種類型。 算…