2017-03-21 83 views
3

我喜歡使用類和方法而不是裸函數。我想知道是否有特定的性能影響(執行速度或內存使用情況或其他方面)。使用方法而不是函數會對性能產生影響嗎?

快速測試顯示,這兩個同樣表現出色:

import timeit 

class Hello: 
    def hello(self): 
     x = 9 * 8 + 3**5 

def world(): 
    x = 9 * 8 + 3 ** 5 

print(timeit.timeit(world, number=10000000)) 
h = Hello() 
print(timeit.timeit(h.hello, number=10000000)) 
# 0.8460009839758439 
# 0.8781686117747095 

在其他測試中,我沒有看到正在使用的RAM更在一種情況下比其他。

是否存在使用類/方法而不是函數時性能會降低的特定情況?

注:我想專注於代碼的性能,而不是美學方面

+0

嘗試將它們包裝在lambda中並再次測試。 –

回答

4

方法調用的開銷實際上只是function對象爲method對象轉換時屬性的訪問(.)上它由一個實例創建的函數屬性。

除此之外,函數的調用也是類似的,爲方法隱含插入一個額外參數(self)。

所以,沒有,真的沒有任何顧慮到這裏,開銷小,可以通過分配方法的局部變量完全消除:

meth = h.hello 
# use meth from now on 

(編輯:在Python 3.7new op-codes其中引入的基本上否定了將h.hello分配到本地名稱的好處,查找方法的速度更快:-)

如果您正在尋找瓶頸,那麼您應該查找其他地方。 Python的動態解釋確實使這些問題變得迂腐。


至於內存方面,方法應該比功能稍大由於基本上含有一個函數作爲它的一個成員的方法:

meth.__func__ # original function object 

儘管這樣,我無法想象一個由於內存開銷方法引入而導致應用程序窒息的場景。

在CPython的,例如,大約64個字節根據getsizeof添加了用於綁定的方法對象:

>>> getsizeof(Foo().foo) 
64 

這不是計數__func__屬性,其中包含function對象:

>>> getsizeof(Foo().foo.__func__) 
136 
1

調用方法obj.method(...)涉及屬性訪問(obj.method部分),這可能是一個不平凡的因此成本很高的操作。一個可能的屬性的訪問情況的簡要描述在documentation of the descriptor protocol發現:

的訪問屬性的默認行爲是獲取,設置或刪除 從對象的字典中的屬性。例如,a.x具有 查找鏈,其從a.__dict__['x']開始,然後是 type(a).__dict__['x'],並且繼續通過除元類之外的基類 type(a)

但是,如果查找的值是定義描述符方法之一的對象,則Python可能會覆蓋默認行爲,而代之以調用描述符方法。在 優先級鏈中發生這種情況取決於定義了哪些描述符方法,以及如何調用這些方法 。

只有在屬性訪問完成後,調用結果可調用對象與調用自由函數幾乎沒有區別。但是,請注意,在您的基準測試中,屬性訪問的開銷(即看起來無害的表達式h.hello後面的操作)未被測量(儘管在您的示例中它應該非常小)。

相關問題