[英]Why is Python's 'len' function faster than the __len__ method?
在 Python 中, len
是一個通過調用對象的__len__
方法來獲取集合長度的函數:
def len(x):
return x.__len__()
所以我希望直接調用__len__()
至少和len()
一樣快。
import timeit
setup = '''
'''
print (timeit.Timer('a="12345"; x=a.__len__()', setup=setup).repeat(10))
print (timeit.Timer('a="12345"; x=len(a)', setup=setup).repeat(10))
但是使用上述代碼的測試結果表明len()
更快。 為什么?
內置的len()
函數不會查找.__len__
屬性。 它查找tp_as_sequence
指針 ,該指針又具有sq_length
屬性 。
內置對象的.__len__
屬性間接映射到同一個插槽 ,而間接(加上屬性查找)需要花費更多時間。
對於Python定義的類,所述type
對象中查找.__len__
的方法時sq_length
被請求。
__len__
比len()
慢,因為__len__
涉及dict查找。
來自優秀的Python Object-Oriented Programming: Build可靠且可維護的面向對象的 Python 應用程序和庫, Steven F. Lott 和 Dusty Phillips 的第 4 版書籍
您可能想知道為什么這些對象沒有 length 屬性,而不必對它們調用函數。 從技術上講,他們確實如此。 len()
將應用於的大多數對象都有一個名為__len__()
的方法,該方法返回相同的值。 所以len(myobj)
似乎調用myobj.__len__()
。
為什么我們應該使用len()
函數而不是__len__()
方法? 很明顯, __len__()
是一個特殊的雙下划線方法,建議我們不要直接調用它。 對此必須有一個解釋。 Python 開發人員不會輕易做出這樣的設計決定。
主要原因是效率。 當我們調用對象的__len__()
方法時,該對象必須在其命名空間中查找該方法,並且,如果特殊的__getattribute__()
方法(每次訪問對象的屬性或方法時都會調用)是在那個對象上定義,它也必須被調用。 此外, __getattribute__()
方法可能是為了做一些聰明的事情而編寫的,例如,拒絕讓我們訪問諸如__len__()
類的特殊方法! len()
函數不會遇到任何這種情況。 它實際上調用底層類的__len__()
方法,因此len(myobj)
映射到MyObj.__len__(myobj)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.