2009-04-07 29 views
110

Qual è la differenza tra:In Python, qual è la differenza tra ".append()" e "+ = []"?

some_list1 = [] 
some_list1.append("something") 

e

some_list2 = [] 
some_list2 += ["something"] 
+3

append se per un singolo elemento. forse intendi "estendi". – hasen

+0

Per il caso più interessante di '+ =' vs 'extend': http://stackoverflow.com/questions/3653298/concatenating-two-lists-difference-between-and-extend –

risposta

153

Per il tuo caso l'unica differenza è la prestazione: append è due volte più veloce.

Python 3.0 (r30:67507, Dec 3 2008, 20:14:27) [MSC v.1500 32 bit (Intel)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import timeit 
>>> timeit.Timer('s.append("something")', 's = []').timeit() 
0.20177424499999999 
>>> timeit.Timer('s += ["something"]', 's = []').timeit() 
0.41192320500000079 

Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import timeit 
>>> timeit.Timer('s.append("something")', 's = []').timeit() 
0.23079359499999999 
>>> timeit.Timer('s += ["something"]', 's = []').timeit() 
0.44208112500000141 

In caso generale append aggiungerà una voce alla lista, mentre += copierà tutti elementi della lista di destra-lato nella lista di sinistra-mano-lato.

Aggiornamento: perf analisi

Confrontando bytecode si può supporre che append versione rifiuti cicli in LOAD_ATTR + CALL_FUNCTION e + = versione - in BUILD_LIST. A quanto pare BUILD_LIST supera LOAD_ATTR + CALL_FUNCTION.

>>> import dis 
>>> dis.dis(compile("s = []; s.append('spam')", '', 'exec')) 
    1   0 BUILD_LIST    0 
       3 STORE_NAME    0 (s) 
       6 LOAD_NAME    0 (s) 
       9 LOAD_ATTR    1 (append) 
      12 LOAD_CONST    0 ('spam') 
      15 CALL_FUNCTION   1 
      18 POP_TOP 
      19 LOAD_CONST    1 (None) 
      22 RETURN_VALUE 
>>> dis.dis(compile("s = []; s += ['spam']", '', 'exec')) 
    1   0 BUILD_LIST    0 
       3 STORE_NAME    0 (s) 
       6 LOAD_NAME    0 (s) 
       9 LOAD_CONST    0 ('spam') 
      12 BUILD_LIST    1 
      15 INPLACE_ADD 
      16 STORE_NAME    0 (s) 
      19 LOAD_CONST    1 (None) 
      22 RETURN_VALUE 

Siamo in grado di migliorare le prestazioni ancora più rimuovendo LOAD_ATTR testa:

>>> timeit.Timer('a("something")', 's = []; a = s.append').timeit() 
0.15924410999923566 
+8

+1: questo è molto interessante. Io uso append comunque, perché risulta in un codice più chiaro. Ma non avevo capito che c'era una differenza di prestazioni. Se mai, mi sarei aspettato che append fosse più lenta, dal momento che è una chiamata di funzione garantita, mentre supponevo che + = sarebbe stata ulteriormente ottimizzata. – DNS

+0

Non c'è anche una differenza funzionale? Per esempio lascia ** a = [] **, ** b = [4,5,6] **, qui se lo fai ** c = a.append (b) ** allora c sarebbe una lista di lista ** [[4,5,6]] ** mentre ** c + = b **; porterebbe a un elenco semplice ** c = [4,5,6] **. – rkioji

+0

solo per impostare le cose: + = offre una prestazione migliore di estendere o aggiungere fino a quando l'input è nel formato giusto. Ciò che richiede tempo nell'esempio corrente è la creazione dell'elenco ['qualcosa']. + = è circa il 15% più veloce – Joe

48

Nell'esempio hai dato, non v'è alcuna differenza, in termini di produzione, tra il append e +=. Ma c'è una differenza tra append e + (che la domanda originariamente chiedeva).

>>> a = [] 
>>> id(a) 
11814312 
>>> a.append("hello") 
>>> id(a) 
11814312 

>>> b = [] 
>>> id(b) 
11828720 
>>> c = b + ["hello"] 
>>> id(c) 
11833752 
>>> b += ["hello"] 
>>> id(b) 
11828720 

Come si può vedere, append e += avere lo stesso risultato; aggiungono l'elemento alla lista, senza produrre una nuova lista. L'utilizzo di + aggiunge i due elenchi e produce un nuovo elenco.

+0

Là * è * la differenza tra append e + =. – Constantin

+3

C'è il fatto che 'append' aggiunge una voce alla lista, mentre + = aggiunge tante quante ce ne sono nell'altra lista (ad esempio alias di' extend'). Ma lui/lei lo sa già, a giudicare dal modo in cui la domanda è stata scritta. C'è qualche altra differenza che mi manca? – DNS

+1

C'è una differenza perché un incarico ampliato introduce il rebinding (spiegazione nella mia risposta). – bobince

20
some_list2 += ["something"] 

è in realtà

some_list2.extend(["something"]) 

per un valore, non c'è differenza. stati di documentazione, che:

s.append(x) stesso come s[len(s):len(s)] = [x]
s.extend(x) stessa s[len(s):len(s)] = x

Così ovviamente s.append(x) è stesse s.extend([x])

39
>>> a=[] 
>>> a.append([1,2]) 
>>> a 
[[1, 2]] 
>>> a=[] 
>>> a+=[1,2] 
>>> a 
[1, 2] 

Sede che accoda aggiunge un singolo elemento di la lista, che può essere qualsiasi cosa. +=[] si unisce alle liste.

+2

Votare questo perché questa è una distinzione importante tra i due. Buon lavoro. – sli

3

Oltre agli aspetti descritti nelle altre risposte, aggiungere e + [] hanno comportamenti molto diversi quando si sta cercando per costruire una lista di liste.

>>> list1=[[1,2],[3,4]] 
>>> list2=[5,6] 
>>> list3=list1+list2 
>>> list3 
[[1, 2], [3, 4], 5, 6] 
>>> list1.append(list2) 
>>> list1 
[[1, 2], [3, 4], [5, 6]] 

list1 + [ '5', '6'] aggiunge '5' e '6' al list1 come singoli elementi. list1.append (['5', '6']) aggiunge la lista ['5', '6'] alla lista1 come un singolo elemento.

27

+ = è un compito. Quando lo usi, stai dicendo "some_list2 = some_list2 + ['something'] '. Assegnazioni coinvolgono rilegatura, quindi:

l= [] 

def a1(x): 
    l.append(x) # works 

def a2(x): 
    l= l+[x] # assign to l, makes l local 
      # so attempt to read l for addition gives UnboundLocalError 

def a3(x): 
    l+= [x] # fails for the same reason 

L'operatore + = dovrebbe anche normalmente creare un nuovo oggetto lista come lista lista + normalmente fa:

>>> l1= [] 
>>> l2= l1 

>>> l1.append('x') 
>>> l1 is l2 
True 

>>> l1= l1+['x'] 
>>> l1 is l2 
False 

Tuttavia nella realtà:

>>> l2= l1 
>>> l1+= ['x'] 
>>> l1 is l2 
True 

Questo perché le liste Python implementano __iadd__() per effettuare un cor- to + = assegnazione aumentata e chiamare invece list.extend(). (È un po 'strano questo: di solito fa quello che volevi dire, ma per motivi di confusione.)

In generale, se stai aggiungendo/esteso un elenco esistente e vuoi mantenere il riferimento al stesso elenco (invece di crearne uno nuovo), è meglio essere espliciti e attenersi ai metodi append()/extend().

5

I test di prestazioni qui non sono corrette:

  1. Non si dovrebbe eseguire il profilo solo una volta.
  2. Se si confronta append vs. + = [] numero di volte, è necessario dichiarare append come funzione locale.
  3. risultati in tempo sono differenti su differenti versioni pitone: 64 e 32 bit

esempio

timeit.Timer ('for i in xrange (100): app (i)', 's = []; app = s.append') timeit()

.

buoni test possono essere trovate qui: http://markandclick.com/1/post/2012/01/python-list-append-vs.html

+0

, i test + = in quella pagina usano '+ = [one_var]'. Se omettiamo di creare elenchi, + = diventa l'opzione più veloce. – Joe

1

Il comportamento rilegatura detto in altre risposte non importa in determinate circostanze:

>>> a = ([],[]) 
>>> a[0].append(1) 
>>> a 
([1], []) 
>>> a[1] += [1] 
Traceback (most recent call last): 
    File "<interactive input>", line 1, in <module> 
TypeError: 'tuple' object does not support item assignment 

Ecco perché l'assegnazione aumentata si ricollega sempre, anche se l'oggetto è stato mutato sul posto. Il rebinding qui sembra essere a[1] = *mutated list*, che non funziona per le tuple.

5

La differenza è che concatenate sarà appiattire la lista risultante, mentre accodamento manterrà i livelli intatti:

Così, per esempio con:

myList = [ ] 
listA = [1,2,3] 
listB = ["a","b","c"] 

Utilizzando accodamento, si finisce con un elenco di elenchi:

>> myList.append(listA) 
>> myList.append(listB) 
>> myList 
[[1,2,3],['a',b','c']] 

Utilizzando concatenate, invece, si finisce con una semplice lista:

>> myList += listA + listB 
>> myList 
[1,2,3,"a","b","c"] 
Problemi correlati