Nessuna delle risposte qui ti fornisce alcun codice con cui lavorare per illustrare veramente perché questo accade in Python land. E questo è divertente da guardare in un approccio più profondo, quindi ecco qui.
Il motivo principale per cui questo non funziona come previsto è perché in Python, quando scrivi:
i += 1
non sta facendo quello che pensi che stia facendo. I numeri interi sono immutabili. Questo può essere visto quando si esamina in che cosa l'oggetto è effettivamente in Python:
a = 0
print('ID of the first integer:', id(a))
a += 1
print('ID of the first integer +=1:', id(a))
La funzione id rappresenta un valore unico e costante per un oggetto nella sua vita. Concettualmente, si associa vagamente a un indirizzo di memoria in C / C ++. Esecuzione del codice precedente:
ID of the first integer: 140444342529056
ID of the first integer +=1: 140444342529088
Questo significa che il primo a
non è più uguale al secondo a
, perché i loro ID sono diversi. Effettivamente sono in posizioni diverse nella memoria.
Con un oggetto, tuttavia, le cose funzionano diversamente. Ho sovrascritto l'operatore +=
qui:
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))
L'esecuzione di questo risultato nel seguente output:
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
Si noti che l'attributo id in questo caso è in realtà stesso per entrambe le iterazioni, anche se il valore dell'oggetto è diverso (si potrebbe anche trovare il id
del valore int dell'oggetto detiene, che cambierebbe mentre si sta mutando - perché gli interi sono immutabili)
Confronta questo con quando esegui lo stesso esercizio con un oggetto immutabile:
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))
Questo produce:
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
Alcune cose qui da notare. Innanzitutto, nel ciclo con +=
, non stai più aggiungendo all'oggetto originale. In questo caso, poiché gli ints sono tra tipi immutabili in Python , python usa un id differente. È anche interessante notare che Python usa lo stesso% co_de sottostante per più variabili con lo stesso valore immutabile:
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 ha una manciata di tipi immutabili, che causano il comportamento che vedi. Per tutti i tipi mutabili, le tue aspettative sono corrette.