2010-11-14 9 views
11

En python, nous pouvons concaténer des listes de deux façons:Est-ce que `extend` est plus rapide que` + = `?

  1. lst.extend (another_lst)
  2. LST + = another_lst

Je pensais que extend serait plus rapide que d'utiliser +=, car réutilise la liste au lieu d'en créer une nouvelle en utilisant les deux autres.

Mais quand je le tester avec timeit, il se avère que += est plus rapide,

>>> 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 

Y at-il quelque chose de mal avec le code que je mets en timeit?

+0

Pouvez-vous nous indiquer les heures que vous avez? De plus, ces opérations sont toutes deux en place, ce qui n'expliquerait aucune différence. –

+0

Je pense que vous devriez utiliser des listes plus grandes, à cette taille minuscule, même la moindre activité de fond pourrait jeter le résultat. – vichle

+0

@ Space_C0wb0y @vischle J'obtiens des résultats cohérents avec ce que Satoru rapporte même avec des listes de plus de 200 éléments. + = est légèrement, mais constamment, plus vite. C'est assez étrange. –

Répondre

17

EDIT: J'ai testé la performance et je ne peux pas reproduire les différences à un niveau significatif.


est ici le bytecode - grâce à @John Machin pour pointer les incohérences.

>>> 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 

Notez que extend utilise un CALL_FUNCTION au lieu d'un INPLACE_ADD. Toute différence de performance triviale peut probablement être attribuée à cela.

+0

Non seulement la recherche d'attribut, mais aussi un appel de fonction. – Constantin

+0

@Constantin, la plupart des attributs de recherche je pense. 'INPLACE_ADD' ne fait qu'emprunter la méthode' __iadd__' qui a été définie sur l'objet. – aaronasterling

+0

@katriealex, @Constantin, @aaronsterling: Sheesh. C'est un LOAD_ATTR et un CALL_FUNCTION par opposition à un INPLACE_ADD ** et un STORE_FAST ** –