Keine der hier aufgeführten Antworten gibt Ihnen Code, mit dem Sie wirklich veranschaulichen können, warum dies im Python-Land passiert. Und es macht Spaß, dies in einem tieferen Sinne zu betrachten, und so geht es weiter.
Der Hauptgrund dafür, dass dies nicht wie erwartet funktioniert, ist, dass Sie in Python Folgendes schreiben:
i += 1
es tut nicht das, was du denkst. Ganzzahlen sind unveränderlich. Dies kann man sehen, wenn man sich anschaut, was das Objekt tatsächlich in Python ist:
a = 0
print('ID of the first integer:', id(a))
a += 1
print('ID of the first integer +=1:', id(a))
Die ID-Funktion repräsentiert einen eindeutigen und konstanten Wert für ein Objekt in seiner Lebensdauer. Konzeptionell ist es einer Speicheradresse in C / C ++ lose zugeordnet. Den obigen Code ausführen:
ID of the first integer: 140444342529056
ID of the first integer +=1: 140444342529088
Dies bedeutet, dass die erste a
nicht mehr mit der zweiten identisch ist a
, da ihre IDs unterschiedlich sind. Tatsächlich befinden sie sich an verschiedenen Stellen im Speicher.
Bei einem Objekt verhält es sich jedoch anders. Ich habe überschreibt die +=
Betreiber hier:
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))
Das Ausführen dieses Befehls führt zu folgender Ausgabe:
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
Beachten Sie, dass das id-Attribut in diesem Fall für beide Iterationen identisch ist , auch wenn der Wert des Objekts unterschiedlich ist (Sie können auch id
den int-Wert des Objekts ermitteln, der sich aufgrund von Ganzzahlen ändern würde, wenn er sich ändert) unveränderlich sind).
Vergleichen Sie dies damit, wenn Sie dieselbe Übung mit einem unveränderlichen Objekt ausführen:
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))
Dies gibt aus:
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
Ein paar Dinge hier zu beachten. Erstens +=
fügen Sie in der Schleife mit dem nicht mehr zum ursprünglichen Objekt hinzu. In diesem Fall verwendet Python eine andere ID , da ints zu den unveränderlichen Typen in Python gehört. Interessant ist auch, dass Python denselben Basiswert id
für mehrere Variablen mit demselben unveränderlichen Wert verwendet:
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 hat eine Handvoll unveränderlicher Typen, die das Verhalten verursachen, das Sie sehen. Für alle veränderlichen Typen ist Ihre Erwartung richtig.
i
unveränderlich ist oder Sie eine nicht mutierende Operation ausführen. Bei einer verschachtelten Listefor i in a: a.append(1)
würde sich das Verhalten ändern. Python nicht die verschachtelten Listen kopieren. Ganzzahlen sind jedoch unveränderlich und Addition gibt ein neues Objekt zurück, es ändert das alte nicht.