2010-11-14 3 views
11

В питона, мы можем объединить списки двумя способами:Является ли `extend` быстрее, чем` + = `?

  1. lst.extend (another_lst)
  2. ЛСТ + = another_lst

Я думал extend будет быстрее, чем при использовании +=, потому что он повторно использует список вместо создания нового, используя два других.

Но когда я проверить его с timeit, то получается, что += быстрее,

>>> timeit('l.extend(x)', 'l = range(10); x = range(10)') 
0.16929602623 
>>> timeit('l += x', 'l = range(10); x = range(10)') 
0.15030503273 
>>> timeit('l.extend(x)', 'l = range(500); x = range(100)') 
0.805264949799 
>>> timeit('l += x', 'l = range(500); x = range(100)') 
0.750471830368 

Есть ли что-то не так с кодом я помещал в timeit?

+0

Можете ли вы показать нам время, которое вы получаете? Кроме того, эти операции являются как на месте, так и не объясняют никакой разницы. –

+0

Я думаю, вы должны использовать более крупные списки, в этом крошечном размере, даже малейшая фоновая активность может привести к сбою результата. – vichle

+0

@ Space_C0wb0y @vischle Я получаю результаты в соответствии с тем, что Satoru сообщает даже со списками из 200+ элементов. + = немного, но последовательно, быстрее. Это довольно странно. –

ответ

17

EDIT: Я тестировал производительность, и я не могу воспроизвести различия до любого значительного уровня.


Вот байт-код - благодаря @John Machin за указание несоответствий.

>>> import dis 
>>> l = [1,2,3] 
>>> m = [4,5,6] 
>>> def f1(l, m): 
...  l.extend(m) 
... 
>>> def f2(l,m): 
...  l += m 
... 
>>> dis.dis(f1) 
    2   0 LOAD_FAST    0 (l) 
       3 LOAD_ATTR    0 (extend) 
       6 LOAD_FAST    1 (m) 
       9 CALL_FUNCTION   1 
      12 POP_TOP 
      13 LOAD_CONST    0 (None) 
      16 RETURN_VALUE 
>>> dis.dis(f2) 
    2   0 LOAD_FAST    0 (l) 
       3 LOAD_FAST    1 (m) 
       6 INPLACE_ADD 
       7 STORE_FAST    0 (l) 
      10 LOAD_CONST    0 (None) 
      13 RETURN_VALUE 

Обратите внимание, что extend использует CALL_FUNCTION вместо с INPLACE_ADD. Вероятно, к этому могут относиться любые тривиальные различия в производительности.

+0

Не только поиск атрибута, но и вызов функции. – Constantin

+0

@Constantin, в основном атрибут поиск думаю. 'INPLACE_ADD' просто маршрутизируется на любой метод' __iadd__', определенный для объекта. – aaronasterling

+0

@katriealex, @Constantin, @aaronsterling: Sheesh. Это LOAD_ATTR и CALL_FUNCTION, а не INPLACE_ADD ** и STORE_FAST ** –

Смежные вопросы