2010-11-22 83 views
6

我最近看着需要創建的三個空單時,到位的[]{}()使用list()dict()tuple(),分別。理由是它看起來更具可讀性。我打算徵求對這種風格的意見,但後來我決定測試性能。我這樣做:爲什麼list(),dict()和tuple()比[],{}和()慢?

>>> from timeit import Timer 
>>> Timer('for x in range(5): y = []').timeit() 
0.59327821802969538 
>>> from timeit import Timer 
>>> Timer('for x in range(5): y = list()').timeit() 
1.2198944904251618 

我試過dict()tuple()list()和每個函數調用的版本是令人難以置信的比語法版本({}[]())那麼差,我有3個問題:

  1. 爲什麼函數調用更昂貴?
  2. 爲什麼這麼差?
  3. 爲什麼在我的計時器中創建5個空列表需要1.2秒?我知道timeit關閉了垃圾回收功能,但是在考慮我僅使用range(5)時,這可能不會起作用。
+0

回覆:風格意見 - 我經常使用[]。我認爲這很清楚。性能問題雖然很有趣。 – nmichaels 2010-11-22 02:32:00

+0

有很多東西看起來很奇怪,直到你習慣了它們。因爲list()實際上可能不是'__builtins __。list',所以我會一直比較喜歡'[]'到'list()'。買家要當心。 – SingleNegationElimination 2010-11-22 02:39:12

回答

18

函數調用需要變量名稱查找,然後是函數調用。調用的函數然後創建一個列表並返回它。該列表的語法文字得到解釋器只是做一個列表:

>>> import dis 
>>> foo = lambda :[] 
>>> bar = lambda :list() 
>>> dis.dis(foo) 
    1   0 BUILD_LIST    0 
       3 RETURN_VALUE   
>>> dis.dis(bar) 
    1   0 LOAD_GLOBAL    0 (list) 
       3 CALL_FUNCTION   0 
       6 RETURN_VALUE   
>>> 
0

範圍查找需要,以便找到dicttuple,並list,以及多個領域需要爲了找到它們進行搜索。使用語法糖時,編譯器可以知道需要創建特定的對象,因此可以發出適當的字節碼來執行此操作。

+1

'[]'對於任何東西都不是語法糖。這是一個列表文字。 – SingleNegationElimination 2010-11-22 02:33:20

+0

@TokenMacGuy:確實是句法糖。列表可以通過調用'list()'來生成,但編譯器會在適當的上下文中將方括號解釋爲創建列表。 – 2010-11-22 02:35:01

+2

編譯器在遇到'[]'時不會*調用'list()'。看到我的答案。 – SingleNegationElimination 2010-11-22 02:36:39

2
>>> from dis import dis 

    >>> dis(lambda: list()) 
    1   0 LOAD_GLOBAL    0 (list) 
       3 CALL_FUNCTION   0 
       6 RETURN_VALUE   

    >>> dis(lambda: []) 
    1   0 BUILD_LIST    0 
       3 RETURN_VALUE   
5

要回答#3。

timeit默認重複您的程序1 000 000次。所以實際上,你在1.2秒內創建500萬個列表。

+0

謝謝。我想下次我應該RTFM :) – orokusaki 2010-11-22 02:50:37

相關問題