Tidak ada jawaban di sini yang memberi Anda kode untuk dikerjakan untuk benar-benar menggambarkan mengapa ini terjadi di tanah Python. Dan ini menyenangkan untuk dilihat dalam pendekatan yang lebih mendalam jadi begini.
Alasan utama bahwa ini tidak berfungsi seperti yang Anda harapkan adalah karena dalam Python, ketika Anda menulis:
i += 1
itu tidak melakukan apa yang Anda pikir sedang dilakukan. Bilangan bulat tidak berubah. Ini bisa dilihat ketika Anda melihat apa objek sebenarnya dalam Python:
a = 0
print('ID of the first integer:', id(a))
a += 1
print('ID of the first integer +=1:', id(a))
Fungsi id mewakili nilai unik dan konstan untuk objek dalam masa pakai itu. Secara konseptual, ini dipetakan secara longgar ke alamat memori dalam C / C ++. Menjalankan kode di atas:
ID of the first integer: 140444342529056
ID of the first integer +=1: 140444342529088
Ini berarti yang pertama a
tidak lagi sama dengan yang kedua a
, karena id mereka berbeda. Secara efektif mereka berada di lokasi yang berbeda dalam memori.
Namun, dengan suatu benda, berbagai hal bekerja secara berbeda. Saya telah menimpa +=
operator di sini:
class CustomInt:
def __iadd__(self, other):
# Override += 1 for this class
self.value = self.value + other.value
return self
def __init__(self, v):
self.value = v
ints = []
for i in range(5):
int = CustomInt(i)
print('ID={}, value={}'.format(id(int), i))
ints.append(int)
for i in ints:
i += CustomInt(i.value)
print("######")
for i in ints:
print('ID={}, value={}'.format(id(i), i.value))
Menjalankan ini menghasilkan output berikut:
ID=140444284275400, value=0
ID=140444284275120, value=1
ID=140444284275064, value=2
ID=140444284310752, value=3
ID=140444284310864, value=4
######
ID=140444284275400, value=0
ID=140444284275120, value=2
ID=140444284275064, value=4
ID=140444284310752, value=6
ID=140444284310864, value=8
Perhatikan bahwa atribut id dalam kasus ini sebenarnya sama untuk kedua iterasi, meskipun nilai objek berbeda (Anda juga bisa menemukan id
nilai int yang dipegang objek, yang akan berubah saat bermutasi - karena bilangan bulat tidak berubah).
Bandingkan dengan ketika Anda menjalankan latihan yang sama dengan objek yang tidak berubah:
ints_primitives = []
for i in range(5):
int = i
ints_primitives.append(int)
print('ID={}, value={}'.format(id(int), i))
print("######")
for i in ints_primitives:
i += 1
print('ID={}, value={}'.format(id(int), i))
print("######")
for i in ints_primitives:
print('ID={}, value={}'.format(id(i), i))
Output ini:
ID=140023258889248, value=0
ID=140023258889280, value=1
ID=140023258889312, value=2
ID=140023258889344, value=3
ID=140023258889376, value=4
######
ID=140023258889280, value=1
ID=140023258889312, value=2
ID=140023258889344, value=3
ID=140023258889376, value=4
ID=140023258889408, value=5
######
ID=140023258889248, value=0
ID=140023258889280, value=1
ID=140023258889312, value=2
ID=140023258889344, value=3
ID=140023258889376, value=4
Beberapa hal yang perlu diperhatikan di sini. Pertama, di loop dengan +=
, Anda tidak lagi menambahkan ke objek asli. Dalam hal ini, karena int adalah salah satu tipe yang tidak dapat diubah dalam Python , python menggunakan id yang berbeda. Juga menarik untuk dicatat bahwa Python menggunakan dasar yang sama id
untuk beberapa variabel dengan nilai tetap yang sama:
a = 1999
b = 1999
c = 1999
print('id a:', id(a))
print('id b:', id(b))
print('id c:', id(c))
id a: 139846953372048
id b: 139846953372048
id c: 139846953372048
tl; dr - Python memiliki beberapa tipe yang tidak dapat diubah, yang menyebabkan perilaku yang Anda lihat. Untuk semua jenis yang bisa berubah, harapan Anda benar.
i
tidak berubah atau Anda sedang melakukan operasi yang tidak bermutasi. Dengan daftar bersarangfor i in a: a.append(1)
akan memiliki perilaku yang berbeda; Python tidak menyalin daftar bersarang. Namun integer tidak dapat diubah dan penambahan mengembalikan objek baru, itu tidak mengubah yang lama.