2017-07-27 109 views
0

Usage of __slots__?讀到,在使用Python __slots__實際上可以節省時間。但是,當我試圖找到使用datetime所花的時間時,結果是相反的。爲什麼使用__slots__減慢這段代碼?

import datetime as t 

class A(): 
    def __init__(self,x,y): 
     self.x=x 
     self.y=y 
t1=t.datetime.now() 
a=A(1,2) 
t2=t.datetime.now() 
print(t2-t1) 

都給輸出:0:00:00.000011 並採用插槽:

import datetime as t 

class A(): 
    __slots__ = 'x','y' 
    def __init__(self,x,y): 
     self.x=x 
     self.y=y 
t1=t.datetime.now() 
a=A(1,2) 
t2=t.datetime.now() 
print(t2-t1) 

都給輸出:0:00:00.000021

使用插槽實際所花的時間。爲什麼我們需要使用__slots__呢?

+0

我注意,手動使用'datetime'這種方式不是用於定時碼的推薦方法。有[用於計時代碼片段的模塊](https://docs.python.org/3/library/timeit.html)。 (正如答案中提到的)你必須多次重複短操作才能使任何事情接近有意義的結果。 –

回答

2
  1. 你報的文章說使用插槽提供了更快的 屬性訪問 - 你測試的對象創建的時間,和 從來沒有訪問您的對象的屬性。
  2. 測試單個操作不是統計意義 - 衡量的,比如100000次行動的時間。
1

__slots__可以節省時間(取決於Python版本),但這通常不是您使用它的原因。它真正節省的是內存。而不是每個實例相當大的__dict__。即使在現代PY3 64與密鑰共享類型的字典,它仍然是一個關鍵的共享__dict__所在班級有一個實例屬性,對對象結構本身的56個字節的最高96個字節。

使用__slots__,你消除對指針的__dict____weakref__屬性的16個字節,並消除__dict__完全。

有關PY 3.5比較:

>>> class Foo: 
... def __init__(self, x): self.x = x 
... 
>>> sys.getsizeof(Foo(1)) + sys.getsizeof(Foo(1).__dict__) 
152 
>>> class Foo: 
... __slots__ = 'x', 
... def __init__(self, x): self.x = x 
... 
>>> sys.getsizeof(Foo(1)) # With __slots__, doesn't have __dict__ at all 
48 

這就是每實例超過100字節的節省;在Py2上(沒有密鑰共享詞典),節省更多。

因此,並不是說__slots__通常速度更快(通常非常相似),但是如果您製作數百萬個實例,則每個實例節省100 + B可能會幫助您將代碼保存在緩存中,RAM等中。 ,而不是耗盡內存並分出一半數據進行交換。

至於對方的回答筆記,你從來沒有真正進入你的屬性,所以你沒有標杆槽接可言,這就是爲什麼你看到的沒有什麼區別的。使用ipython3%%timeit魔法,我發現反覆加載給定實例的屬性x約15%的速度時,它的開槽(33.5 ns有__slots__與39.2納秒無),但這只是在明顯的微基準;它在真正的代碼中很少重要(實際的工作不僅僅是屬性查找)。重要的是,將內存使用量減少2-3倍是更大的收益。