Listeler ve Shallow Copy, Sığ Kopyalama Kavramı
14-2.04.04
Bir listeyi dilimlediğimiz zaman, slice, yeni bir list nesnesi oluşmaktadır.
Ancak bu yeni nesnenin liste elemanları da dilimlediğimiz listenin elemanlarında
tutulan adresleri tutmaktadır. Yani dilimleme esnasında listenin elemanlarının
gösterdiği nesnelerden yeni kopyalar oluşturulup daha sonra bu yeni kopyalar
yeni liste tarafından gösterilmez. Bu işlem shallow copy yani sığ
kopyalama olarak geçmektedir. Her iki liste, yeni ve orijinali, aynı nesneleri
gösterir.
Bunu hemen deneyebiliriz.
>>> x = [1, 2, 3, 4, 5]
>>> y = x[2:4]
>>> y[0] is x[2]
True
>>> y[1] is x[3]
True
görüldüğü gibi aynı nesne gösterilmektedir liste elemanları tarafından.
Genel kültür: Eğer liste elemanlarının gösterdiği nesnelerden de yeni kopyalar oluşturuluyor ve yeni liste bunları gösteriyor olsaydı bu sefer deep copy yani derin kopyalama yapılıyor olacaktı. Python’da sığ kopyalama yapılmaktadır.
Bu davranışın getirdiği çeşitli bizi şaşırtabilen sonuçlar olabilir. Aşağıdaki duruma bakalım:
x = [1, [2, 3, 4], 5]
Burada liste içerisinde bir liste vardır.
>>> y = x[0:2]
>>> y
[1, [2, 3, 4]]
yaptığımız zaman x ten bir dilim aldık ve yi oluşturduk.
>>> y[1][0] = 100
>>> y
[1, [100, 3, 4]]
>>> x
[1, [100, 3, 4], 5]
y[1][0] = 100 ifadesi ile içerideki listenin ilk elemanını 100 yaptık fakat
bu durumda x in içeriği de değişti. Listeler değiştirilebilir yani mutable
nesneler olduğu için böyle bir durum oluşmaktadır.
Neden? Biz dilimleme yapıp yyi oluşturduğumuz zaman y[1] aslında x[1]
in de gösterdiği 3 eleman barındıran iç listeyi göstermektedir. Hemen
ispatlayalım:
>>> x[1] is y[1]
True
Biz y[1][0] = 100 ile iç listenin ilk elemanının başka bir int nesnesini
göstermesini sağladık. Ama x[1] ile y[1] aynı 3 elemanlı iç listeyi
gösterdiği için aslında x in içeriği de güncellenmiş oldu.
Çizimlerle bellek organizasyonunu biraz daha iyi anlayalım:
İlk durum
Shallow copy yapıldığı için yeni listenin elemanları da orijinal listenin elemanları ile aynı nesneleri gösteriyorlar.
y[1][0] = 100 dediğimizde içerideki liste artık değeri 2 olan int nesneyi
değil, yeni yaratılan ve değeri 100 olan başka bir int nesneyi gösteriyor.
Ama artık x de günün sonunda aynı içeriği gösteriyor. Kullanılmayan ve
değeri 2 olan int nesnesi Python implementasyonu tarafından bir noktada
“çope atılacak”, garbage collector ve benzeri yapılarla. int değiştirilemez
yani immutable bir nesne olduğu için yenisi yaratıldı ama list
değiştirilebilir olduğu için değeri güncellendi yani başka nesneyi gösterir
oldu.
Elbette x[0] ı değiştirirsek y[0] değişmeyecektir.
>>> x[0] = 500
>>> x
[500, [100, 3, 4], 5]
>>> y
[1, [100, 3, 4]]
15-0.00.00