Sorunun geçmişi: Python'da nesnelerin (özellikle koleksiyonların — listeler, sözlükler) kopyalanması kritik öneme sahiptir: bir değişkene basit atama yapmak, bir kopya değil, yalnızca yeni bir referans oluşturur. copy() ve deepcopy() özel yöntemleri, yapıların birlikte kullanımında istenmeyen "yan etkileri" önlemek için ortaya çıktı.
Problem: İç içe koleksiyonlarla (liste içinde liste, sözlük içinde sözlük) çalışırken, basit copy() yalnızca kap container'ı kopyalar, ancak iç öğeleri kopyalamaz. Bu, iç içe öğelerin değiştirilmesinin tüm "kopyalarda" yansımasına neden olabilen zor yakalanan hatalara yol açabilir.
Çözüm: copy.copy() yüzeysel bir kopya (shallow copy) oluşturur — üst düzeyde yeni bir container ama içteki nesneler aynı kalır. copy.deepcopy() tüm iç nesneleri özyinelemeli olarak kopyalar.
Kod örneği:
import copy lst = [[1, 2], [3, 4]] shallow = copy.copy(lst) deep = copy.deepcopy(lst) lst[0][0] = 10 print(shallow) # [[10, 2], [3, 4]] — iç nesne değişti! print(deep) # [[1, 2], [3, 4]] — deepcopy orijinal durumu korudu
Ana özellikler:
Bazen lst2 = lst[:] yazmak yeterli mi?
lst2 = lst[:] listeyi yüzeysel bir şekilde kopyalar, ancak iç nesneler (örneğin, listeler içindeki listeler) yine de aynıdır. Düz listeler için bu yeterlidir; iç içe yapılar için değildir.
Örnek:
lst = [[1], [2]] lst2 = lst[:] lst[0][0] = 99 print(lst2) # [[99], [2]] — iç nesne her iki "kopyada" değişti
Tüm koleksiyonlar için .copy() yöntemi aynı şekilde çalışır mı?
Hayır. Örneğin, dict.copy() yüzeysel kopyalama yapar, list.copy() yalnızca Python 3.3 ile gelmiştir, set için — set.copy() vardır. Kullanıcı nesneleri için .copy() desteği, uygulanan metoda bağlıdır.
Her yerde deepcopy ile yetinmek mümkün mü? Güvenli ve verimli mi?
Hayır. deepcopy, pahalı bir işlemdir: büyük yapılar üzerinde performans sorunlarına neden olabilir ve kopyalanamayan/kapalı veya standart dışı nesnelerde bozulabilir. deepcopy'i yalnızca gerçekten tamamen bağımsız, özyinelemeli kopyalama gerektiğinde kullanın.
Testlerde "sözlük içinde sözlük" kopyalamak için dict.copy() kullanıldı. Bu nedenle, bir kullanıcının iç yapısındaki değişiklikler, diğer testleri beklenmedik şekilde etkiledi (veriler küresel olarak değişti).
Artılar:
Eksiler:
copy.deepcopy() uygulandı, belgelerde her nesnenin yapı özelliklerini ve içerik düzeyini tanımladık, büyük miktarlarda derin kopyalamaktan kaçındık, parçalar halinde "manuel" kopyalamaya yöneldik.
Artılar:
Eksiler: