🐍 SIFIRDAN İLERİ SEVİYEYE PYTHON EĞİTİM SERİSİ - BÖLÜM 4

================================================================================
🐍 SIFIRDAN İLERİ SEVİYEYE PYTHON EĞİTİM SERİSİ - BÖLÜM 4
================================================================================

Selamlar Değerli Forum Sakinleri! 🚀🔥

OOP, MRO algoritması ve Metasınıfların büyüleyici dünyasını geride bıraktık.
Şimdi fonksiyonel programlamanın bellek dostu mimarilerine ve Python'ın en
zarif yapılarına giriş yapıyoruz: **Bölüm 4!** ☕💻

Bu bölümde:
1. Closure (Kapanış) Mantığı ve `__closure__` Hücreleri
2. Decorator (Bezeyici) Mimarisi ve Wrappers
3. Iterators, Generators ve `yield` Protokolü (Lazy Evaluation)

--------------------------------------------------------------------------------
1. Fonksiyon İçi Bellek Koruması: Closure (Kapanış) 🔒
--------------------------------------------------------------------------------
Bir fonksiyon icra edildikten sonra yerel (local) değişkenleri bellekten
(stack) silinir. Ancak iç içe geçmiş fonksiyonlarda, içteki fonksiyon dıştaki
fonksiyonun değişkenini "hapsettiyse" buna **Closure** denir.

CPython bu durumu `cell` (hücre) adı verilen özel bellek alanlarında tutar.

Teorik Kod ve Bellek Hücresi İncelemesi:
def dis_us_al(taban):
# 'taban' değişkeni dis_us_al çalışması bitse bile silinmeyecek!
def ic_hesapla(us):
return taban ** us
return ic_hesapla

kare_al = dis_us_al(2)
kup_al = dis_us_al(3)

print(kare_al(4)) # 16 (2^4)
print(kup_al(3)) # 27 (3^3)

# Arka planda korunan hücre değerlerini doğrulama:
print(kare_al.__closure__[0].cell_contents) # Output: 2
print(kup_al.__closure__[0].cell_contents) # Output: 3

--------------------------------------------------------------------------------
2. Decorator (Bezeyici) Mimarisi ve Sintaktik Şeker 🍬
--------------------------------------------------------------------------------
Decorator'lar, var olan bir fonksiyonun davranışını kodunu değiştirmeden
genişletmeye yarayan Closure yapılardır. `@decorator_adi` kullanımı tamamen
bir "Syntactic Sugar" (Sintaktik Şeker) işlemidir.

Eşdeğer Mantık:
@loglayici
def topla(a, b): return a + b

# Yukarıdaki satır, arka planda BİREBİR şuna dönüşür:
# topla = loglayici(topla)

Teorik Süre Analiz Decorator'ı:
import time
from functools import wraps

def zaman_olc(func):
@wraps(func) # Fonksiyonun __name__ ve __doc__ metadata'sını korur
def wrapper(*args, **kwargs):
baslangic = time.perf_counter()
sonuc = func(*args, **kwargs)
bitis = time.perf_counter()
print(f"[LOG] {func.__name__} çalışma süresi: {(bitis - baslangic):.6f} sn")
return sonuc
return wrapper

@zaman_olc
def agir_islem():
return sum(i * i for i in range(1_000_000))

agir_islem()

--------------------------------------------------------------------------------
3. Generator, Iterator ve yield Protokolü ⚡
--------------------------------------------------------------------------------
Klasik listeler tüm veriyi RAM'e doldurur. Ancak milyarlarca veriden oluşan bir
süreçte bu durum `MemoryError` fırlatır.

Python burada **Lazy Evaluation (Tembel Değerlendirme)** ilkesini uygular:
"Veri istendiği an üretilsin, bellekte tutulmasın!"

A) Iterator Protokolü (`__iter__` ve `__next__`):
Bir nesnenin iterator olabilmesi için `__iter__()` (kendini döndüren) ve
`__next__()` (sonraki elemanı döndüren / bitince `StopIteration` fırlatan)
metotlarına sahip olması gerekir.

B) Generator ve `yield` İç Mimarisi:
Bir fonksiyonda `return` yerine `yield` kullanıldığında, fonksiyon çağrıldığında
çalışmaz; geriye bir Generator Nesnesi döndürür.

`yield` komutuna gelindiğinde CPython fonksiyonun durumunu (Local değişkenler,
Instruction Pointer) dondurur ve değeri dışarı fırlatır. Bir sonraki `next()`
çağrısında kaldığı yerden devam eder!

Bellek Farkı (List Comprehension vs Generator Expression):
import sys

# List Comprehension (Tüm 1 Milyon elemanı RAM'e basar)
liste = [x ** 2 for x in range(1_000_000)]
print(f"Liste RAM Kullanımı: {sys.getsizeof(liste)} bayt") # ~8 MB!

# Generator Expression (Sadece üretim kuralını tutar, veri RAM'de YOKTUR)
generator = (x ** 2 for x in range(1_000_000))
print(f"Generator RAM Kullanımı: {sys.getsizeof(generator)} bayt") # Sadece ~200 Bayt!

# Teker teker veriyi çekme:
print(next(generator)) # 0
print(next(generator)) # 1
print(next(generator)) # 4

--------------------------------------------------------------------------------
4. Bölüm Özeti ve Gelecek Adım 📌
--------------------------------------------------------------------------------
Bu bölümde Closure bellek hücrelerini, Decorator mimarisini ve devasa verileri
sıfır bellek tüketimiyle işleyen Generator/yield yapısını inceledik.

Devam etmek için forum başlığı altına "DEVAM" yazmanız yeterlidir!

Bir sonraki bölümde (Bölüm 5):
- Eşzamanlılık (Concurrency) ve Paralellik (Parallelism)
- GIL (Global Interpreter Lock) Nedir, Neden Var, Nasıl Bypassed Edilir?
- `threading`, `multiprocessing` ve `asyncio` Derin İncelemesi

Sorularınızı ve teorik katk
ılarınızı aşağıda bekliyorum! 🚀✨
================================================================================

🔒 Bu içeriği görmek için giriş yapın

 
Yanıt yazmak için giriş yapmalısınız
Forum özelliklerini kullanmak ve Level 2 üyelik satın almak için hesabınıza giriş yapın.
135,050Konular
3,297,703Mesajlar
326,233Kullanıcılar
membiSon Üye
Üst Alt