Ini sepenuhnya tergantung pada objek i
.
+=
memanggil __iadd__
metode (jika ada - mundur kembali __add__
jika tidak ada) sedangkan +
memanggil __add__
metode 1 atau __radd__
metode dalam beberapa kasus 2 .
Dari perspektif API, __iadd__
seharusnya digunakan untuk memodifikasi objek yang bisa berubah di tempat (mengembalikan objek yang dimutasi) sedangkan __add__
seharusnya mengembalikan contoh baru dari sesuatu. Untuk objek yang tidak dapat diubah , kedua metode mengembalikan instance baru, tetapi __iadd__
akan menempatkan instance baru di namespace saat ini dengan nama yang sama dengan instance lama. Ini sebabnya
i = 1
i += 1
tampaknya meningkat i
. Pada kenyataannya, Anda mendapatkan integer baru dan menetapkannya "di atas" i
- kehilangan satu referensi ke integer lama. Dalam hal ini, i += 1
persis sama dengan i = i + 1
. Tapi, dengan sebagian besar objek yang bisa berubah, ini adalah cerita yang berbeda:
Sebagai contoh nyata:
a = [1, 2, 3]
b = a
b += [1, 2, 3]
print a #[1, 2, 3, 1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
dibandingkan dengan:
a = [1, 2, 3]
b = a
b = b + [1, 2, 3]
print a #[1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
pemberitahuan bagaimana dalam contoh pertama, karena b
dan a
referensi objek yang sama, ketika saya menggunakan +=
pada b
, itu benar-benar berubah b
(dan a
melihat perubahan itu juga - Setelah semua, itu referensi daftar yang sama). Namun dalam kasus kedua, ketika saya melakukannya b = b + [1, 2, 3]
, ini mengambil daftar yang b
mereferensikan dan menyatukannya dengan daftar baru [1, 2, 3]
. Itu kemudian menyimpan daftar gabungan di namespace saat ini sebagai b
- Tanpa memperhatikan apa b
baris sebelumnya.
1 Dalam ekspresi x + y
, jika x.__add__
tidak diimplementasikan atau jika x.__add__(y)
kembali NotImplemented
dan x
dan y
memiliki jenis yang berbeda , maka x + y
cobalah menelepon y.__radd__(x)
. Jadi, dalam kasus di mana Anda miliki
foo_instance += bar_instance
jika Foo
tidak menerapkan __add__
atau __iadd__
hasilnya di sini sama dengan
foo_instance = bar_instance.__radd__(bar_instance, foo_instance)
2 Dalam ekspresi foo_instance + bar_instance
, bar_instance.__radd__
akan dicoba sebelumnya foo_instance.__add__
jika jenisnya bar_instance
adalah subkelas dari jenis foo_instance
(misalnya issubclass(Bar, Foo)
). Rasional untuk ini adalah karena Bar
dalam beberapa arti "-tingkat yang lebih tinggi" objek dari Foo
sehingga Bar
harus mendapatkan pilihan utama Foo
perilaku 's.
+=
bertindak sepertiextend()
dalam kasus daftar.