Dalam Python, apa perbedaan antara “.append ()” dan “+ = []”?


122

Apa perbedaan antara:

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

dan

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

3
tambahkan jika untuk satu item. mungkin maksudmu extend.
hasen


Jawaban:


161

Untuk kasus Anda, satu-satunya perbedaan adalah kinerja: menambahkan dua kali lebih cepat.

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

Secara umum appendakan menambahkan satu item ke daftar, sementara +=akan menyalin semua elemen daftar sisi kanan ke daftar sisi kiri.

Pembaruan: analisis kinerja

Membandingkan bytecode, kita dapat mengasumsikan bahwa appendversi membuang siklus dalam LOAD_ATTR+ CALL_FUNCTION, dan + = versi - in BUILD_LIST. Ternyata BUILD_LISTmelebihi 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

Kami dapat lebih meningkatkan kinerja dengan menghilangkan LOAD_ATTRoverhead:

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

12
+1: Ini sangat menarik. Saya tetap menggunakan append, karena menghasilkan kode yang lebih jelas. Tetapi saya tidak menyadari ada perbedaan kinerja. Jika ada, saya berharap menambahkan menjadi lebih lambat, karena ini adalah panggilan fungsi yang dijamin, sementara saya menganggap + = akan dioptimalkan lebih lanjut.
DNS

2
Bukankah ada juga perbedaan fungsional? Misalkan a = [] , b = [4,5,6] , di sini jika Anda melakukan c = a.append (b) maka c akan menjadi daftar daftar [[4,5,6]] sedangkan c + = b ; akan mengarah ke daftar sederhana c = [4,5,6] .
rph

hanya untuk meluruskan semuanya: + = memberikan kinerja yang lebih baik daripada memperpanjang atau menambahkan selama masukan Anda dalam format yang benar. Apa yang membutuhkan waktu dalam contoh saat ini adalah pembuatan daftar ['sesuatu']. + = sekitar 15% lebih cepat
Joe

@Joe Jika Anda membandingkan appendvs +=, maka Anda harus menyertakan pembuatan daftar sebagai bagian dari pengukuran. Jika tidak, itu akan menjadi pertanyaan yang berbeda ( extendvs +=).
jamesdlin

@jameslin yup! Tetapi mudah untuk salah kecuali Anda sudah mengetahui hal ini. Sedikit tambahan presisi tidak akan pernah menyakiti siapa pun, bukan?
Joe

48

Dalam contoh yang Anda berikan, tidak ada perbedaan, dalam hal keluaran, antara appenddan +=. Tetapi ada perbedaan antara appenddan +(pertanyaan mana yang awalnya ditanyakan).

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

Seperti yang Anda lihat, appenddan +=memiliki hasil yang sama; mereka menambahkan item ke daftar, tanpa membuat daftar baru. Menggunakan +menambahkan dua daftar dan menghasilkan daftar baru.


Ada adalah perbedaan antara append dan + =.
Constantin

3
Ada fakta yang appendmenambahkan satu entri ke daftar, sementara + = menambahkan sebanyak yang ada di daftar lainnya (yaitu alias extend). Tapi dia sudah tahu itu, dilihat dari cara pertanyaan itu ditulis. Apakah ada perbedaan lain yang saya lewatkan?
DNS

1
Ada perbedaan karena tugas tambahan memperkenalkan rebinding (penjelasan dalam jawaban saya).
bobince

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

Lihat bahwa menambahkan menambahkan satu elemen ke daftar, yang bisa berupa apa saja. +=[]bergabung dengan daftar.


2
Memilih ini karena ini adalah perbedaan penting antara keduanya. Kerja bagus.

31

+ = adalah tugas. Ketika Anda menggunakannya, Anda benar-benar mengatakan 'some_list2 = some_list2 + [' sesuatu ']'. Tugas melibatkan pengikatan ulang, jadi:

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

Operator + = biasanya juga membuat objek list baru seperti list + list biasanya:

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

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

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

Namun kenyataannya:

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

Ini karena daftar Python mengimplementasikan __iadd __ () untuk membuat sirkuit pendek tugas tambahan + = dan memanggil list.extend () sebagai gantinya. (Ini agak aneh kutil ini: biasanya melakukan apa yang Anda maksud, tetapi untuk alasan yang membingungkan.)

Secara umum, jika Anda menambahkan / memperluas daftar yang sudah ada, dan Anda ingin menyimpan referensi ke daftar yang sama (daripada membuat yang baru), sebaiknya eksplisit dan tetap dengan append () / memperpanjang () metode.


21
 some_list2 += ["something"]

sebenarnya

 some_list2.extend(["something"])

untuk satu nilai, tidak ada perbedaan. Dokumentasi menyatakan, bahwa:

s.append(x) sama s[len(s):len(s)] = [x]
s.extend(x) sepertis[len(s):len(s)] = x

Jadi jelas s.append(x)sama dengans.extend([x])


s.append mengambil tipe sembarang dan menambahkannya ke daftar; Itu pelengkap yang benar. s.extend mengambil iterable (biasanya berupa daftar), dan menggabungkan iterable menjadi s, memodifikasi alamat memori s. Ini tidak sama.
W4t3randWind

9

Perbedaannya adalah bahwa concatenate akan meratakan daftar yang dihasilkan, sedangkan append akan menjaga level tetap utuh:

Jadi misalnya dengan:

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

Menggunakan append, Anda akan mendapatkan daftar daftar:

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

Menggunakan penggabungan sebagai gantinya, Anda berakhir dengan daftar datar:

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

5

Tes kinerja di sini tidak benar:

  1. Anda tidak boleh menjalankan profil hanya sekali.
  2. Jika membandingkan append vs. + = [] berapa kali Anda harus mendeklarasikan append sebagai fungsi lokal.
  3. hasil waktu berbeda pada versi python yang berbeda: 64 dan 32 bit

misalnya

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

tes yang baik dapat ditemukan di sini: http://markandclick.com/1/post/2012/01/python-list-append-vs.html


tetap saja, + = tes di halaman itu menggunakan += [one_var]. Jika kita menghilangkan pembuatan daftar, + = menjadi pilihan tercepat.
Joe

3

Selain aspek yang dijelaskan dalam jawaban lain, append dan + [] memiliki perilaku yang sangat berbeda saat Anda mencoba membuat daftar.

>>> 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'] menambahkan '5' dan '6' ke list1 sebagai elemen individual. list1.append (['5', '6']) menambahkan daftar ['5', '6'] ke list1 sebagai satu elemen.


2

Perilaku rebinding yang disebutkan dalam jawaban lain memang penting dalam keadaan tertentu:

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

Itu karena penugasan yang bertambah selalu mem-rebind, bahkan jika objek dimutasi di tempat. Rebinding di sini kebetulan a[1] = *mutated list*, yang tidak bekerja untuk tupel.


0

mari kita ambil contoh dulu

list1=[1,2,3,4]
list2=list1     (that means they points to same object)

if we do 
list1=list1+[5]    it will create a new object of list
print(list1)       output [1,2,3,4,5] 
print(list2)       output [1,2,3,4]

but if we append  then 
list1.append(5)     no new object of list created
print(list1)       output [1,2,3,4,5] 
print(list2)       output [1,2,3,4,5]

extend(list) also do the same work as append it just append a list instead of a 
single variable 

0

Metode append () menambahkan satu item ke daftar yang ada

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

Jadi di sini some_list1 akan dimodifikasi.

Diperbarui:

Sedangkan menggunakan + untuk menggabungkan elemen list (lebih dari satu elemen) pada list yang ada mirip dengan extender (seperti yang dikoreksi oleh Flux ).

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

Jadi di sini some_list2 dan ["sesuatu"] adalah dua daftar yang digabungkan.


1
Ini salah. +=tidak mengembalikan daftar baru. The Programming FAQ mengatakan: "... untuk daftar, __iadd__setara dengan memanggil extendpada daftar dan kembali daftar itu sebabnya kami mengatakan bahwa untuk daftar,. +=Adalah 'singkatan' untuk list.extend". Anda juga dapat melihatnya sendiri di kode sumber CPython: github.com/python/cpython/blob/v3.8.2/Objects/…
Flux

0

"+" tidak mengubah daftar

.append () mengubah daftar lama

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.