Buradaki cevapların hiçbiri, bunun neden Python bölgesinde olduğunu göstermek için üzerinde çalışacağınız herhangi bir kod vermedi. Ve bu daha derin bir yaklaşıma bakmak eğlencelidir, işte burada.
Bunun beklediğiniz gibi çalışmamasının birincil nedeni, Python’da yazmanızdır.
i += 1
yaptığını düşündüğün şeyi yapmıyor. Tamsayılar değişmezdir. Bu, nesnenin Python'da gerçekte ne olduğuna baktığınızda görülebilir:
a = 0
print('ID of the first integer:', id(a))
a += 1
print('ID of the first integer +=1:', id(a))
İd işlevi , kullanım ömrü boyunca bir nesne için benzersiz ve sabit bir değeri temsil eder. Kavramsal olarak, C / C ++ 'da bir hafıza adresine gevşek olarak eşler. Yukarıdaki kodu çalıştırıyor:
ID of the first integer: 140444342529056
ID of the first integer +=1: 140444342529088
Bunun anlamı, birincisinin a
artık ikinciyle aynı olmadığı a
, çünkü kimlikleri farklı. Etkili bir biçimde bellekteki farklı konumlardalar.
Bununla birlikte, bir nesneyle, işler farklı şekilde çalışır. +=
Burada operatörün üzerine yazdım :
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))
Bu sonuç aşağıdaki çıktıyla sonuçlanır:
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
Bu durumda id niteliğinin aslında her iki yineleme için aynı olduğuna dikkat edin , nesnenin değeri farklı olsa da ( id
nesnenin mutasyona uğradığı için değişecek olan nesnenin tuttuğu int değerini de bulabilirsiniz) değişmez).
Bunu aynı egzersizi değişmez bir nesneyle yaptığınız zaman karşılaştırın:
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))
Bu çıktılar:
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
Burada dikkat edilmesi gereken birkaç şey var. İlk olarak, ile olan döngüde +=
, artık orijinal nesneye ekleyemezsiniz. Bu durumda, girişler Python'daki değişmez türler arasında olduğundan , python farklı bir kimlik kullanır. Ayrıca Python'un id
aynı değişmez değere sahip birden fazla değişken için aynı temeli kullandığını not etmek ilginç :
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, gördüğünüz davranışa neden olan bir avuç değişmez tipe sahiptir. Tüm değişken tipler için beklentiniz doğrudur.
i
değişmez ise veya değişmeyen bir işlem yapıyorsanız geçerlidir . İç içe geçmiş bir liste ilefor i in a: a.append(1)
farklı davranış olacaktır; Python gelmez iç içe listeleri kopyalayın. Ancak tamsayılar değişmez ve ekleme yeni bir nesne döndürür, eskisini değiştirmez.