Jika kami mengambil b = [1,2,3]
dan jika kami mencoba melakukan:b+=(4,)
Itu kembali b = [1,2,3,4]
, tetapi jika kami mencoba melakukannya b = b + (4,)
tidak berhasil.
b = [1,2,3]
b+=(4,) # Prints out b = [1,2,3,4]
b = b + (4,) # Gives an error saying you can't add tuples and lists
Saya berharap b+=(4,)
gagal karena Anda tidak dapat menambahkan daftar dan tupel, tetapi berhasil. Jadi saya mencoba b = b + (4,)
berharap untuk mendapatkan hasil yang sama, tetapi tidak berhasil.
python
python-3.x
list
tuples
Supun Dasantha Kuruppu
sumber
sumber
Jawaban:
Masalah dengan pertanyaan "mengapa" adalah bahwa biasanya mereka dapat berarti banyak hal yang berbeda. Saya akan mencoba menjawab masing-masing yang saya pikir mungkin ada dalam pikiran Anda.
"Kenapa itu bisa bekerja secara berbeda?" yang dijawab oleh misalnya ini . Pada dasarnya,
+=
cobalah untuk menggunakan metode objek yang berbeda:__iadd__
(yang hanya diperiksa di sisi kiri), vs__add__
dan__radd__
("reverse add", dicentang di sisi kanan jika sisi kiri tidak memiliki__add__
) untuk+
."Apa tepatnya yang dilakukan setiap versi?" Singkatnya,
list.__iadd__
metode ini melakukan hal yang samalist.extend
(tetapi karena desain bahasa, masih ada tugas kembali).Ini juga berarti misalnya itu
+
, tentu saja, membuat objek baru, tetapi secara eksplisit membutuhkan daftar lain daripada mencoba menarik elemen dari urutan yang berbeda."Mengapa bermanfaat untuk + = untuk melakukan ini? Ini lebih efisien;
extend
metode ini tidak harus membuat objek baru. Tentu saja, ini kadang-kadang memiliki beberapa efek mengejutkan (seperti di atas), dan umumnya Python tidak benar-benar tentang efisiensi , tapi keputusan ini dibuat sejak lama."Apa alasannya untuk tidak memperbolehkan menambahkan daftar dan tupel dengan +?" Lihat di sini (terima kasih, @ splash58); satu ide adalah bahwa (tuple + list) harus menghasilkan jenis yang sama dengan (list + tuple), dan tidak jelas jenis hasil yang seharusnya.
+=
tidak memiliki masalah ini, karenaa += b
jelas tidak boleh mengubah jenisa
.sumber
|
, sehingga agak merusak contoh saya. Jika saya memikirkan contoh yang lebih jelas nanti saya akan menukarnya.|
untuk set adalah operator komuter tetapi+
untuk list tidak. Untuk alasan itu saya tidak berpikir argumen tentang tipe ambiguitas sangat kuat. Karena operator tidak bepergian mengapa memerlukan jenis yang sama? Orang bisa saja setuju bahwa hasilnya memiliki tipe lhs. Di sisi lain, dengan membatasilist + iterator
, pengembang didorong untuk lebih eksplisit tentang niat mereka. Jika Anda ingin membuat daftar baru yang berisi barang-barang daria
diperpanjang oleh barang-barang darib
sudah ada cara untuk melakukan ini:new = a.copy(); new += b
. Ini satu garis lagi tapi sangat jelas.a += b
berperilaku berbeda daripadaa = a + b
bukan efisiensi. Sebenarnya Guido menganggap perilaku yang dipilih itu kurang membingungkan. Bayangkan sebuah fungsi menerima daftara
sebagai argumen dan kemudian melakukana += [1, 2, 3]
. Sintaksis ini jelas terlihat seperti memodifikasi daftar di tempat, daripada membuat daftar baru, sehingga keputusan dibuat bahwa itu harus berperilaku sesuai dengan intuisi kebanyakan orang tentang hasil yang diharapkan. Namun, mekanismenya juga harus bekerja untuk tipe yang tidak berubah sepertiint
s, yang menyebabkan desain saat ini.a += b
singkatana = a + b
, seperti yang dilakukan Ruby, tapi saya bisa mengerti bagaimana kami sampai di sana.Mereka tidak setara:
adalah singkatan untuk:
saat
+
menggabungkan daftar, jadi dengan:Anda mencoba menyatukan tuple ke daftar
sumber
Ketika Anda melakukan ini:
dikonversi menjadi ini:
Di bawah tenda yang dipanggilnya
b.extend((4,))
,extend
terima iterator dan inilah mengapa ini juga berfungsi:tetapi ketika Anda melakukan ini:
dikonversi menjadi ini:
hanya menerima objek daftar.
sumber
Dari dokumen resmi, untuk jenis urutan yang dapat berubah, keduanya:
didefinisikan sebagai:
Yang berbeda dari yang didefinisikan sebagai:
Ini juga berarti semua jenis urutan akan berfungsi
t
, termasuk tupel seperti pada contoh Anda.Tapi itu juga berfungsi untuk rentang dan generator! Misalnya, Anda juga dapat melakukan:
sumber
Operator penugasan "augmented" seperti
+=
diperkenalkan dalam Python 2.0, yang dirilis pada Oktober 2000. Desain dan alasannya dijelaskan dalam PEP 203 . Salah satu tujuan yang dinyatakan dari operator ini adalah dukungan operasi di tempat. Penulisanseharusnya memperbarui daftar
a
di tempat . Ini penting jika ada referensi lain ke daftara
, misalnya ketikaa
diterima sebagai argumen fungsi.Namun, operasi tidak selalu dapat terjadi di tempat, karena banyak tipe Python, termasuk bilangan bulat dan string, tidak dapat diubah , jadi misalnya
i += 1
untuk bilangan bulati
tidak mungkin beroperasi di tempat.Singkatnya, operator penugasan augmented seharusnya bekerja di tempat bila memungkinkan, dan membuat objek baru sebaliknya. Untuk memfasilitasi sasaran desain ini, ekspresi
x += y
ditentukan untuk berperilaku sebagai berikut:x.__iadd__
didefinisikan,x.__iadd__(y)
dievaluasi.x.__add__
diterapkanx.__add__(y)
dievaluasi.y.__radd__
diterapkany.__radd__(x)
dievaluasi.Hasil pertama yang diperoleh oleh proses ini akan ditugaskan kembali
x
(kecuali jika hasil itu adalahNotImplemented
singleton, dalam hal ini pencarian dilanjutkan dengan langkah berikutnya).Proses ini memungkinkan jenis yang mendukung modifikasi di tempat untuk menerapkan
__iadd__()
. Jenis yang tidak mendukung modifikasi di tempat tidak perlu menambahkan metode sihir baru, karena Python akan secara otomatis kembali ke dasarnyax = x + y
.Jadi mari kita akhirnya datang ke pertanyaan Anda yang sebenarnya - mengapa Anda dapat menambahkan tuple ke daftar dengan operator penugasan augmented Dari memori, sejarah ini kira-kira seperti ini:
list.__iadd__()
Metode ini diterapkan untuk memanggil metode yang sudah adalist.extend()
di Python 2.0. Ketika iterator diperkenalkan dengan Python 2.1,list.extend()
metode ini diperbarui untuk menerima iterator yang sewenang-wenang. Hasil akhir dari perubahan ini adalah yangmy_list += my_tuple
bekerja mulai dari Python 2.1. Thelist.__add__()
metode, bagaimanapun, tidak pernah seharusnya mendukung iterator sewenang-wenang sebagai argumen kanan - ini dianggap tidak pantas untuk bahasa sangat diketik.Saya pribadi berpikir implementasi dari operator augmented menjadi agak terlalu rumit dalam Python. Ini memiliki banyak efek samping yang mengejutkan, misalnya kode ini:
Baris kedua memunculkan
TypeError: 'tuple' object does not support item assignment
, tetapi operasi tetap berhasil dilakukan -t
akan([42, 44], [43])
setelah mengeksekusi baris yang memunculkan kesalahan.sumber
Kebanyakan orang akan mengharapkan X + = Y setara dengan X = X + Y. Memang, Referensi Saku Python (edisi ke-4) oleh Mark Lutz mengatakan pada halaman 57 "Dua format berikut kira-kira setara: X = X + Y, X + = Y ". Namun, orang-orang yang menentukan Python tidak membuatnya setara. Mungkin itu adalah kesalahan yang akan menghasilkan berjam-jam waktu debugging oleh programmer frustrasi selama Python tetap digunakan, tetapi sekarang hanya seperti itu Python. Jika X adalah tipe urutan yang bisa berubah, X + = Y setara dengan X.extend (Y) dan bukan X = X + Y.
sumber
Seperti yang dijelaskan di sini , jika
array
tidak menerapkan__iadd__
metode,b+=(4,)
itu hanya singkatanb = b + (4,)
tetapi jelas tidak, begituarray
juga__iadd__
metode implement . Rupanya implementasi__iadd__
metode adalah seperti ini:Namun kita tahu bahwa kode di atas bukanlah implementasi
__iadd__
metode yang sebenarnya tetapi kita dapat mengasumsikan dan menerima bahwa ada sesuatu sepertiextend
metode, yang menerimatupple
input.sumber