Bölüm 9 · Yazılımın içi · Ders 42
Yığın, öbek ve closure
Yol planlayıcının özyinelemeli çağrıları bellekte ne yapar?
Veri. Depo robotu 10 ara noktadan geçen bir rotanın uzunluğunu hesaplıyor. Fonksiyon özyinelemeli: 'buradan hedefe uzunluk = bir sonraki noktaya mesafe + oradan hedefe uzunluk'. Her çağrı yığına bir çerçeve koyar; ara noktalar ise öbekte, bir listede durur. Robotun gömülü bilgisayarında yığın küçüktür; burada 16 çerçeveyle sınırladık.
import math, sysN, SINIR = 10, 16 # çağrı sayısı, yığın sınırısys.setrecursionlimit(SINIR + 1) # +1: modül çerçevesinoktalar = [(i, i * 7 % 5) for i in range(N)] # öbektedef uzunluk(i): # i'den hedefe yol (m)p = noktalar[i] # öbekteki demete referansif i == N - 1:return 0.0 # son nokta: çerçeve silinird = math.dist(p, noktalar[i + 1])return d + uzunluk(i + 1) # yeni çerçeve yığınatry:print('yol:', round(uzunluk(0), 2), 'm')except RecursionError:print('yığın taşması: sınır', SINIR, 'çerçeve')def sayac_yap():n = 0 # hücre (cell) nesnesine taşınırdef say():nonlocal nn += 1return nreturn say # çerçeve gider, hücre kalırs = sayac_yap()print(s(), s(), s()) # 1 2 3print(s.__closure__[0].cell_contents) # 3
Sahnedeki her sayı, aynı algoritmanın tarayıcında yapılan gerçek çalıştırmasından gelir (sabit tohum, her seferinde aynı sonuç). Python kodunu kendi bilgisayarında çalıştırırsan rastgele başlangıçlar farklı olacağı için sayılar biraz değişebilir.
Veri seti
Tüm veri setleri →Bu dersin kodu verisini kendi içinde üretir; indirilecek dosya yok. Kodu yine de aşağıda tarayıcında çalıştırabilirsin.
Kodu tarayıcıda çalıştırPython · NumPy · matplotlib · Pyodide
Python ve NumPy bu sayfada, tarayıcında çalışır (Pyodide). Kodu değiştirip yeniden çalıştırabilirsin; dersin veri setleri çalışma klasöründe hazır. Kod matplotlib kullanırsa grafikler çıktının altında görünür, yazdığı dosyalar (ör. egitim_gecmisi.csv) indirilebilir.
Çıktı
Çıktı burada görünecek.Nasıl çalışır
- Yığın: her çağrı için bir çerçeve (yerel değişkenler, dönüş adresi). Fonksiyon dönünce çerçeve hemen silinir; sırası hep "son giren ilk çıkar".
- Öbek: nesnelerin yaşadığı alan (liste, demetler). Çerçevedeki değişken nesnenin kendisi değil, ona bir referanstır (ok). Nesne, ona işaret eden kalmayınca silinir.
- Özyineleme derinliği kadar çerçeve aynı anda yığında durur. Sınırı aşan çağrı RecursionError (yığın taşması) verir.
- Closure: iç fonksiyon dış fonksiyonun değişkenini kullanıyorsa Python o değişkeni bir hücre (cell) nesnesine taşır. Dış çerçeve silinse de hücre öbekte yaşar; sayaç değerini çağrılar arasında korur.
- Şunu dene: derinliği 17 yap; 17. çağrı yığına sığmaz ve taşma olur.
Neden önemli
Mikrodenetleyicilerde yığın birkaç kilobayttır; derin özyineleme ya da büyük yerel diziler robotu sessizce çökertir, bu yüzden gömülü kodda yol arama genelde döngü ve açık bir kuyrukla yazılır. Closure ise geri çağırmalarda (sensör olayı, zamanlayıcı) durumu taşımanın en kısa yoludur.
ESOF 323, 11. hafta: robotlarda derin öğrenme →