İçeriğe geç

Menü

Berk Akademi
Yorumlar Google yorumları Özel Ders Başvuru Ücretsiz ön görüşme Ana Sayfa

Python “dictionary changed size during iteration” Hatası Neden Çıkar?

python-dictionary-changed-size-during-iteration-hatasi
Bu yazıda neler var?
  1. Sözlüğü gezerken bu hata neden oluşur?
  2. Anahtarların kopyası üzerinde nasıl dönülür?
  3. Sözlük üreteciyle nasıl yeni bir sözlük oluşturulur?
  4. Silinecek anahtarlar önce nasıl toplanır?

Python’da dictionary changed size during iteration hatası, bir sözlüğü döngüyle gezerken aynı sözlüğe anahtar eklenmesi veya sözlükten anahtar silinmesi nedeniyle oluşur. Döngünün takip ettiği anahtar yapısı değiştiğinde Python güvenli biçimde ilerleyemediği için RuntimeError üretir.

Ürün stoklarını tutan bir sözlükte sıfır stoklu ürünleri doğrudan döngü sırasında silmek bu hatanın yaygın örneklerinden biridir. Çözüm için önce anahtarların ayrı bir kopyası üzerinde dönmek, sözlüğü daha sonra değiştirmek gerekir.

Sözlüğü gezerken bu hata neden oluşur?

Sözlüğü gezerken bu hata neden oluşur?

Sözlüğü döngüyle gezerken del veya pop() kullanarak bir anahtar silersen sözlüğün boyutu değişir. Python dokümantasyonu da sözlük üzerinde dolaşma sürerken giriş eklenmesinin veya silinmesinin RuntimeError oluşturabileceğini ya da bazı girdilerin atlanmasına yol açabileceğini belirtir.

Aşağıdaki örnekte amaç, stok değeri sıfır olan ürünleri sözlükten çıkarmaktır:

stoklar = {
    "kalem": 12,
    "defter": 0,
    "silgi": 5,
    "dosya": 0
}

for urun, stok in stoklar.items():
    if stok == 0:
        del stoklar[urun]

print(stoklar)

Bu kodda defter anahtarı silindiği anda sözlüğün boyutu değişir. Döngü aynı sözlükte gezinmeye devam etmeye çalıştığı için çalışma sırasında şu hata alınır:

RuntimeError: dictionary changed size during iteration

Buradaki sorun, for döngüsünün kullanılması değildir. Sorun, döngünün üzerinde ilerlediği sözlüğün yapısının döngü bitmeden değiştirilmesidir. Aynı durum yeni bir anahtar eklemek için stoklar["mouse"] = 8 yazıldığında da ortaya çıkabilir.

pop() kullanmak da bu kuralı değiştirmez. Örneğin stoklar.pop(urun) ifadesi, ilgili anahtarı sözlükten sildiği için döngü sırasında kullanıldığında aynı türden bir sorun oluşturabilir.

keys() çağrısı da otomatik olarak kopya üretmez. stoklar.keys(), sözlüğün anahtarlarını gösteren dinamik bir görünüm sağlar ve özgün sözlükteki değişikliklerden etkilenir. Bu nedenle for urun in stoklar.keys(): yazmak, silme işlemini güvenli hâle getirmez.

Boyut değişmeden yalnızca mevcut bir anahtarın değerini güncellemek ise bu özel hatayı oluşturmaz. Örneğin döngü içinde stoklar[urun] = stok + 1 yazmak anahtar sayısını değiştirmediği için sözlüğün yapısını büyütmez veya küçültmez.

Anahtarların kopyası üzerinde nasıl dönülür?

Özgün sözlükte silme yaparken güvenli bir yöntem, döngüyü list(stoklar) ile oluşturulan ayrı anahtar listesi üzerinde çalıştırmaktır. Böylece döngü sırasında değişmeyen bir listeyi gezersin, silme işlemi ise özgün sözlükte yapılır.

stoklar = {
    "kalem": 12,
    "defter": 0,
    "silgi": 5,
    "dosya": 0
}

for urun in list(stoklar):
    if stoklar[urun] == 0:
        del stoklar[urun]

print(stoklar)

Bu kodun çıktısı şöyledir:

{'kalem': 12, 'silgi': 5}

list(stoklar) ifadesi sözlüğün anahtarlarından yeni bir liste oluşturur. Döngü bu sabit listeyi gezerken del işlemi özgün sözlük üzerinde gerçekleşir. Yöntem mevcut sözlüğü doğrudan değiştirdiği için işlem sonrasında sıfır stoklu ürünler sözlükte bulunmaz; ayrıca anahtar listesini oluşturmak için ek bellek kullanılır.

Sözlük üreteciyle nasıl yeni bir sözlük oluşturulur?

Sözlük üreteciyle nasıl yeni bir sözlük oluşturulur?

Sözlüğü döngüyle gezerken mevcut sözlüğün içine silme ya da ekleme yapmak yerine, koşulu sağlayan kayıtları yeni bir sözlükte toplayabilirsin. Sözlük üretecinde items() kullanıldığında her turda anahtar ve değer birlikte alınır. Bu örnekte ürün adı urun, stok miktarı ise adet değişkenine atanıyor.

stok = {
    "kalem": 12,
    "defter": 0,
    "silgi": 7,
    "dosya": 0
}

stoklu_urunler = {
    urun: adet
    for urun, adet in stok.items()
    if adet > 0
}

print(stoklu_urunler)

Bu kodun çıktısı şöyledir:

{'kalem': 12, 'silgi': 7}

urun: adet bölümü yeni sözlüğe hangi anahtar ve değerin yazılacağını belirler. if adet > 0 koşulu ise yalnızca stoğu bulunan ürünleri seçer. Burada stok sözlüğü döngü sırasında değiştirilmez, sonuç ayrı bir sözlükte oluşturulur.

Sonucun ayrı bir isimle tutulmasına gerek yoksa yeni sözlüğü aynı değişken adına da atayabilirsin:

stok = {
    urun: adet
    for urun, adet in stok.items()
    if adet > 0
}

Bu kullanım, filtrelenmiş sözlüğü doğrudan stok değişkenine bağlar. Eski sözlük nesnesi yerinde küçültülmez, stok adı yeni oluşturulan sözlüğü göstermeye başlar.

Silinecek anahtarlar önce nasıl toplanır?

Silme kararını sözlüğü döngüyle gezerken verip, del işlemini döngü tamamlandıktan sonra uygulayabilirsin. Böylece karar verme aşamasında üzerinde dolaşılan sözlüğün boyutu değişmez.

stok = {
    "kalem": 12,
    "defter": 0,
    "silgi": 7,
    "dosya": 0
}

silinecekler = []

for urun, adet in stok.items():
    if adet == 0:
        silinecekler.append(urun)

for urun in silinecekler:
    del stok[urun]

print(stok)

Bu kodun çıktısı şöyledir:

{'kalem': 12, 'silgi': 7}

Bu yaklaşımda ilk döngü yalnızca hangi anahtarların silineceğini belirler. İkinci döngü ise belirlenen anahtarları sözlükten çıkarır. Silme koşulunu daha karmaşık bir işlemden sonra uygulamak veya silinecek anahtarları başka bir yerde kullanmak istediğinde bu ayrım okunabilirliği artırır.

Hangi yöntemin uygun olduğu yapmak istediğin işleme göre değişir:

  • Mevcut sözlüğün aynı nesne olarak kalması gerekiyorsa, anahtarları önce bir listede toplayıp sonra silebilirsin.
  • Filtrelenmiş veriyi ayrı bir sonuç olarak üretmek daha anlaşılırsa, sözlük üreteci kullanabilirsin.
  • Silme kararını başka kontrollerden sonra vermek istiyorsan, karar listesini oluşturup silme işlemini sonraki aşamaya bırakabilirsin.

Aynı dikkat kümeler için de geçerlidir. Bir kümeyi döngüyle gezerken eleman eklemek veya silmek, kümenin boyutunu değiştirdiği için RuntimeError: Set changed size during iteration hatasına yol açabilir. CPython kaynak kodunda küme yineleyicisi için kullanılan hata metni bu şekildedir.

urunler = {"kalem", "defter", "silgi"}

for urun in urunler:
    urunler.add("dosya")

Sözlükte olduğu gibi burada da değişikliği döngü sonrasına taşımak veya değişecek verilerden ayrı bir koleksiyon oluşturmak daha güvenli bir akış sağlar.

Bu hatayı önlemenin ortak noktası, döngüyle gezilen koleksiyonun yapısını aynı döngü içinde değiştirmemektir. Yeni veri üretmek, anahtarları önce toplamak ya da değişikliği sonraki aşamaya bırakmak kodu daha öngörülebilir hâle getirir.

Bu içerik aradığın cevabı verdi mi?
Yanıtın, hangi yazıları geliştirmemiz gerektiğini anlamamıza yardımcı olur.
Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

Bu konudan sonra ne okuyabilirsin?

Tüm yazılar

İlgili Eğitimler

Berk Keskin, yazılım geliştirici ve eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; İzmir Ekonomi Üniversitesi'ni bölüm birincisi ve yüksek şeref öğrencisi olarak tamamladı. Bugün yalnızca eğitim vermekle kalmıyor, sektörde aktif olarak yazılım projeleri geliştiriyor ve gerçek dünya deneyimini birebir derslerine taşıyor. Ezberden uzak, mühendislik zihniyetini merkeze alan sürdürülebilir öğrenme sistemleri tasarlayarak sorgulayan, üreten ve problem çözebilen yeni nesil yazılımcılar yetiştiriyor.

Sektörel Deneyim & Projeler

  • Ticarify Entegrasyon Yazılım logosu CEO Ticarify Entegrasyon YazılımPazaryerleri ve e-ticaret sitelerine otomatik e-fatura kesimi, sipariş ve kargo takibi hizmetleri sunan e-Dönüşüm platformunun API mimarisini ve yazılım ekibini yönetmektedir.
  • Benim Düğünüm logosu CEO Benim DüğünümDijital etkinlik ve anı paylaşım platformu.
  • Siberdizayn logosu Yazılım Ekibi Lideri SiberdizaynYüksek anlık oyuncu trafiğine sahip oyun kontrol panelleri ve sunucu altyapıları geliştiren yazılım ekibine liderlik etmektedir.
  • MEDYOGRAFYA 360° Dijital Çözümler logosu Dijital Strateji Lideri MEDYOGRAFYA 360° Dijital ÇözümlerŞirketlerin dijital çözümlerde uzun vadede nasıl ilerlemesi gerektiği ve dijital dönüşüm süreçlerinin yönetilmesine destek olmaktadır.
  • İzmir Ekonomi Üniversitesi logosu Danışma Kurulu Üyesi İzmir Ekonomi ÜniversitesiMezun olduğu üniversitesinde, Bilgisayar Programcılığı bölümünün akademik müfredatını güncel sektör ihtiyaçlarına göre şekillendirmek adına Danışma Kurulu'nda görev almaktadır.
WhatsApp Hemen Ara