6  Fonksiyonlar

def + returnnn.Module.forward()’in atası

NotBölüm bilgisi

6.1 Bu Derste Ne Var?

Şimdiye kadar yazdığımız her kod “düzüne” çalıştı: satır 1 → satır 2 → satır 3. Yeniden kullanmak istediğimizde kopya-yapıştır ettik. Bu sağlıklı değil. Çözüm: fonksiyon — kodu adlandırılmış, yeniden çağırılabilir bir blokta toplama.

flowchart LR
    A["def name():"] --> B["Parametreler"]
    B --> C["return değer"]
    C --> D["💡 print ≠ return"]
    D --> E["Default args"]
    E --> F["Scope (lokal/global)"]
    F --> G["💎 Pure function"]
    G --> H["➡️ nn.Module.forward()"]

    style A fill:#e3f2fd,stroke:#3776ab,stroke-width:2px
    style G fill:#fff3e0,stroke:#f57c00,stroke-width:2px
    style H fill:#fce4ec,stroke:#c2185b,stroke-width:3px
Şekil 6.1: Ders 5’in akış haritası — def’ten nn.Module.forward()’a

Dersin beş parçası:

  1. def ile fonksiyon tanımı.
  2. Parametreler ve argümanlar.
  3. return ifadesi.print ile karıştırma!
  4. Default + keyword argumanlar.
  5. Scope. — Lokal vs global.
İpucuBuilder Notu — Bu Dersin ML Köprüleri
  • Fonksiyon = nn.Module.forward()’in atası. Mosh’un def greet(name): print(...), PyTorch’ta class Net(nn.Module): def forward(self, x): return self.layer(x) ile birebir aynı yapı. Sinir ağı = fonksiyon kompozisyonu.
  • return = computation graph node. PyTorch’ta return ile dönen tensor autograd tarafından izlenir.
  • Parameters = hyperparameters. def train(lr=0.001, epochs=100): Mosh’un parametre kavramının ML hâli.
  • Default args = kütüphane sağduyu değerleri. nn.Linear(bias=True), nn.Dropout(p=0.5) — kullanıcı sadece değiştirmek istediğini belirtir.
  • Pure function (saf fonksiyon) = parallelizable + cached. JAX jit, PyTorch torch.compile — hepsi saf fonksiyon gerekir.
  • Multi-param + keyword arg = ML standartları. model.forward(x, mask=None, cache=None).

6.2 def ile Fonksiyon Tanımı

Mosh:

“fonksiyonlar bir fonksiyon sadece bir kod koleksiyonu, belirli bir görevi yerine getiren” — Mosh (Türkçe dublaj), 1:24:21

6.2.1 Sentaks

“fonksiyon yazmak istersem ilk kullanmam gereken şey python içinde bir anahtar kelime def denir” — Mosh (Türkçe dublaj), 1:25:18

def greet():
    print("Merhaba!")

Dört parça:

  • def — anahtar kelime.
  • greet — fonksiyon adı (snake_case, PEP 8).
  • () — parametre listesi (boş).
  • : — gövde başlangıç işareti.

Sonraki satır(lar) girintili olmalı — standart 4 boşluk.

6.2.2 Çağırma

“Bir işlevin içindeki kod sadece onu çalıştırmak istediğimizi belirttiğimizde çalıştırılacak.” — Mosh (Türkçe dublaj), 1:28:23

Sadece def ile yazmak çalıştırmaz. Tanımlar, saklar. Çağırmak için:

def greet():
    print("Merhaba!")

greet()        # () ile cagri - şimdi çalışır
# Merhaba!

greet()        # bir kere daha
# Merhaba!

Yeniden kullanılabilirlik — fonksiyon yaratmanın en büyük kazancı.

6.2.3 Girintilik — Python’un Disiplin Kuralı

def greet():
    print("Merhaba!")     # girintili = fonksiyon içinde
    print("Hos geldin!")  # girintili = fonksiyon içinde

print("Bu dışarıda.")     # girinti yok

Java/C/JavaScript { } ile belirler; Python sadece boşluk ile. ML kodu yüzlerce satır olabilir; sağlıklı indent disiplini olmadan okunamaz.

6.2.4 Builder Notu — PyTorch’ta def

İpucuBuilder Notu — Modelin İskeleti

Mosh’un en basit def greet(): örneği, PyTorch’taki model tanımının iskeletidir:

import torch.nn as nn

# Mosh'un seviyesi:
def greet():
    print("Merhaba!")

# PyTorch'un ayni mantigi:
class Greeter(nn.Module):
    def forward(self):
        print("Merhaba!")

# Kullanim - ayni:
greet()              # fonksiyonu çağır
model = Greeter()
model()              # PyTorch modulu cagir = forward() calisir

Sadece class sarmalı + __call__ zekası eklenmiş. Temel kavram aynı: fonksiyon → çağrılır → işi yapar.

6.3 Parametreler

Sabit metin basan greet() çok sınırlı. Çoğu zaman veri vermek isteriz.

“fonksiyon yazdığımızda çoğu zaman, daha fazla bilgiye sahip olmak isteyeceğiz. ve bunlara parametreler denir.” — Mosh (Türkçe dublaj), 1:30:37

6.3.1 Tek Parametre

def greet(name):
    print("Merhaba " + name + "!")

greet("Deniz")     # Merhaba Deniz!
greet("Aylin")     # Merhaba Aylin!
greet("Mosh")      # Merhaba Mosh!
  • name parametresi — fonksiyon tanımında parantezdeki isim.
  • "Deniz" argümanı — fonksiyon çağrılırken geçilen değer.

6.3.2 Çoklu Parametre

def greet(name, age):
    print(f"Merhaba {name}, sen {age} yasindasin!")

greet("Deniz", 35)
greet("Aylin", 28)

6.3.3 Type Hints (Modern Python)

Mosh göstermez; modern ML kodunda yoğun:

def greet(name: str, age: int) -> None:
    print(f"Merhaba {name}, sen {age} yasindasin!")

Python runtime tipi zorlamıyor (çağrıda yanlış tip → hata olmaz) ama statik analiz (mypy, pyright) yakalar.

6.3.4 ML’in Çoklu Parametre Standardı

İpucuBuilder Notu — Transformer Forward

Modern ML modelleri çok parametreli fonksiyonlardır:

class TransformerLayer(nn.Module):
    def forward(self, x, mask=None, cache=None, return_attn=False):
        # x: input tensor (batch, seq_len, d_model)
        # mask: opsiyonel attention mask
        # cache: opsiyonel KV cache (generation icin)
        # return_attn: attention weights donsun mu?
        ...
        return output

Dört parametre: x (zorunlu), mask, cache, return_attn (üçü default’lu). Mosh’un def greet(name, age): öğrettiği yapı, bu modelin forward fonksiyonunun çekirdek pattern’ı.

PyTorch konvansiyonları:

  • İlk: self — instance referansı (Ders 12).
  • İkinci: x — ana tensor input.
  • Sonraki: mask, cache, vs. — opsiyonel modifier’lar, default’lu.

6.4 return İfadesi

“bazen bir fonksiyon çağırdığımızda aslında almak isteyeceğiz bilgi geri Bu fonksiyondan.” — Mosh (Türkçe dublaj), 1:34:40

6.4.2 Birden Fazla Değer

Ders 4’te (Tuple Unpacking) öngörmüştük:

def istatistik(nums):
    return min(nums), max(nums), sum(nums) / len(nums)

en_kucuk, en_buyuk, ortalama = istatistik([5, 2, 8, 1, 9, 3])

return a, b, c aslında return (a, b, c) — tuple döner. PyTorch’ta:

output, hidden = lstm_layer(x)            # 2 deger
logits, attn = transformer(x, return_attn=True)

6.4.3 Erken return ile Guard Clause

def bol(a, b):
    if b == 0:
        return None       # erken cikis - hata durumunda None
    return a / b

print(bol(10, 2))      # 5.0
print(bol(10, 0))      # None

6.4.4 return = Computation Graph Node

İpucuBuilder Notu — Autograd Zinciri

PyTorch’ta return ile döndürülen tensor autograd graph’ında bir düğümdür:

import torch

def my_model(x, w, b):
    z = x @ w + b              # linear transform
    a = torch.relu(z)          # activation
    return a                   # bu DUGUM autograd ile izlenir

w = torch.randn(3, 5, requires_grad=True)
b = torch.randn(5, requires_grad=True)
x = torch.randn(10, 3)

output = my_model(x, w, b)
loss = output.sum()
loss.backward()                 # autograd, my_model'den geri gider
print(w.grad)                   # w'nin gradient'i hesaplanmis

PyTorch loss.backward() çağrısında bu satırların türevini alır. Mosh’un mikro return num * num * num’ı, ML autograd sisteminin atasıdır.

Şekil 6.2: Mosh’un def cube(num): return num**3 mikro örneği vs PyTorch forward — aynı yapı

6.5 Default Argumanlar

Mosh göstermez ama modern Python’da her yerde.

def greet(name="Misafir"):
    print(f"Merhaba {name}!")

greet()              # Merhaba Misafir!     (argüman yok - default)
greet("Deniz")       # Merhaba Deniz!       (argüman default'u eziyor)

6.5.1 Birden Fazla Default + Keyword Argument

def kullanici_yarat(ad, yas=18, sehir="Istanbul", rol="user"):
    print(f"{ad} ({yas}), {sehir}, rol: {rol}")

# Sirayla:
kullanici_yarat("Deniz")
# Deniz (18), Istanbul, rol: user

# Karısık - keyword ile:
kullanici_yarat("Deniz", rol="admin")
# Deniz (18), Istanbul, rol: admin

kullanici_yarat(ad="Aylin", sehir="Ankara", yas=28)
# Aylin (28), Ankara, rol: user

name=value syntax’ı isim ile belirtir. Sıra önemsiz.

UyarıMutable Default Tuzağı

Yaygın Python tuzağı:

# YANLIS:
def liste_ekle(yeni, liste=[]):
    liste.append(yeni)
    return liste

print(liste_ekle(1))    # [1]
print(liste_ekle(2))    # [1, 2]  ← HATA! Onceki cagrinin sonucu kaldi
print(liste_ekle(3))    # [1, 2, 3]

Default [] fonksiyon tanımlandığında bir kere yaratılır; tüm çağrılar aynı listeyi paylaşır.

Doğru pattern:

def liste_ekle(yeni, liste=None):
    if liste is None:
        liste = []
    liste.append(yeni)
    return liste

Mutable default (list, dict, set) yerine None kullan ve fonksiyon içinde initialize et.

6.5.2 ML Kütüphanelerinde Default’lar

PyTorch katmanları çok parametreli + default’lu:

import torch.nn as nn

# nn.Linear: bias=True default
layer = nn.Linear(in_features=784, out_features=128)   # bias eklenir
layer_no_bias = nn.Linear(784, 128, bias=False)

# nn.Conv2d: bir sürü default
conv = nn.Conv2d(
    in_channels=3,
    out_channels=64,
    kernel_size=3,
    stride=1,           # default
    padding=0,          # default
    dilation=1,         # default
    bias=True,          # default
)

Eğitim fonksiyonu tipik hali:

def train(
    model,
    train_loader,
    val_loader,
    epochs=100,
    lr=1e-3,
    weight_decay=1e-5,
    log_interval=10,
    device="cuda",
    early_stopping=True,
    patience=5,
):
    ...

On parametre, dokuzu default.

6.6 Scope — Lokal ve Global

Fonksiyon kendi içinde değişkenler yaratabilir. Bu değişkenler dışarıdan görünmez.

6.6.1 Lokal Değişken

def hesapla():
    x = 10
    y = 20
    return x + y

print(hesapla())     # 30
print(x)             # NameError: name 'x' is not defined

6.6.2 Global Değişken

LEARNING_RATE = 0.001     # global

def train():
    print(f"LR: {LEARNING_RATE}")     # global'i okur

train()                   # LR: 0.001

Ama yazmak için global keyword:

counter = 0

def increment():
    global counter
    counter += 1

6.6.3 Pure Function — Yan Etkisi Olmayan

ML’in en sevdiği pattern:

# Pure - iyi:
def kare(x):
    return x * x

# Kirli (global modification):
toplam = 0
def ekle(x):
    global toplam
    toplam += x
İpucuBuilder Notu — Saf Fonksiyon = ML Performansı

JAX’in jit decorator’ı saf fonksiyon zorunluluğu:

import jax

@jax.jit
def model_forward(x, w, b):
    return jax.nn.relu(jax.numpy.dot(x, w) + b)

Bu fonksiyon:

  • Sadece (x, w, b)’ye bağlı.
  • Yan etkisi yok.
  • Çıktı deterministik.
  • Paralel çalıştırılabilir.
  • GPU/TPU’da JIT compile edilir.

PyTorch’ta torch.compile, modern Python’da functools.cache — hepsi saf fonksiyon gerekir. Mosh’un öğrettiği scope kavramı, modern ML pratiğinin felsefi temeli.

6.7 Docstring — Fonksiyonu Belgele

def kup(num):
    """Verilen sayinin kupunu doner.

    Args:
        num: Kupü alinacak sayi (int veya float).

    Returns:
        num * num * num
    """
    return num * num * num

Üç tırnak ("""...""") ile yazılan ilk string = docstring. help(kup) ile görünür. PyTorch ve NumPy’nin milyonlarca satırlık kodu docstring’lerle dolu.

6.8 Bu Dersin Özeti

  1. def name(params): — fonksiyon tanımı.
  2. Çağrı name(args) — fonksiyonu çalıştırır.
  3. return x — değer döndürür. Yoksa None.
  4. returnprint — KARIŞTIRMA. ML’de kritik.
  5. Default arg def f(x=0): — opsiyonel parametre.
  6. Keyword arg f(x=5) — sırayı önemsizleştirir.
  7. Lokal scope — fonksiyon içi değişkenler dışarıdan görünmez.
  8. Pure function — yan etkisi yok = ML altın standart.
  9. Mutable default tuzağıdef f(x=[]): YASAK; None sentinel.
  10. Docstring """...""" — belgele.
ÖnemliTek Bir Cümle

Fonksiyon = adlandırılmış, parametre alabilen, değer döndürebilen kod bloğudur (def name(params): return value) — Python’da gerçek programcı olmanın eşiği ve PyTorch’taki nn.Module.forward(self, x)’in dolaysız atasıdır; return ile döndürülen tensor autograd grafiğinde bir düğüm olur ve loss.backward() ile takip edilir; default argümanlar modern ML kütüphanelerinin standardıdır; lokal scope disiplini = saf fonksiyon disiplini = JAX jit, PyTorch torch.compile performans optimizasyonlarının temelidir.

6.9 Egzersizler

Egzersiz 1. Üç matematik fonksiyon — kare, küp, ondördüncü kuvvet:

def kare(x):
    return ???

def kup(x):
    return ???

def ondord_kuvvet(x):
    return ???

print(kare(5))           # 25
print(kup(3))            # 27
print(ondord_kuvvet(2))  # 16384

Egzersiz 2. Selamlama — name zorunlu, selam+noktalama default:

def selamla(name, selam="Merhaba", noktalama="!"):
    print(f"{selam} {name}{noktalama}")

# 5 çağrı için çıktıyı önceden tahmin et:
selamla("Deniz")
selamla("Aylin", "Selam")
selamla("Mosh", noktalama=".")
selamla(name="Steve", selam="Hi")
selamla("Kelly", noktalama="?", selam="Naber")

Egzersiz 3. (Multi-return) Liste istatistiği:

def istatistik(nums):
    return ???   # min, max, mean, sum tuple

nums = [5, 2, 8, 1, 9, 3, 7, 4, 6]
en_kucuk, en_buyuk, ortalama, toplam = istatistik(nums)

Egzersiz 4. (Saf fonksiyon disiplini) Aşağıdaki yan-etkili kodu saf hale getir:

# YAN ETKİLİ:
toplam_skor = 0
notlari = []

def not_ekle(yeni):
    global toplam_skor
    notlari.append(yeni)
    toplam_skor += yeni
    print(f"Yeni: {yeni}, toplam: {toplam_skor}")

Saf versiyonu yaz — global yok, print dışında.

Egzersiz 5. (Builder eksen — fake neural network forward)

def linear_layer(x, w, b):
    return ???   # y = x * w + b

def relu(x):
    return ???   # max(0, x)

def model_forward(x, w1, b1, w2, b2):
    z1 = linear_layer(x, w1, b1)
    a1 = relu(z1)
    z2 = linear_layer(a1, w2, b2)
    return z2

x = 3.0
w1, b1 = 2.0, 1.0
w2, b2 = 0.5, -1.0

output = model_forward(x, w1, b1, w2, b2)
print(f"Output: {output}")
# Beklenen: 2.5 (3*2+1=7, relu(7)=7, 7*0.5-1=2.5)

Mosh’un öğrettiği fonksiyon kavramının gerçek PyTorch model forward pattern’ı ile birebir aynı yapı olduğunu gösterir. Sadece skaler yerine tensor, ve requires_grad=True ile autograd çalışır.

6.10 Sonraki Ders İçin Hazırlık

Ders 6: Karar Yapıları

Mosh’un Ch 16-18 (If, Comparisons, Better Calculator). Şu ana kadar kod doğrusal akıyordu; Ders 6’da dallandırma ekleyeceğiz.

  • Mosh’un Ch 16-18’ini izle (1:40:09-2:07:20, ~27 dk).
  • Şu cümleyi içselleştir:if programa dal seçme yeteneği verir.”
İpucuBu dersten tek bir şey alıp gideceksen

def name(params): return value — adlandırılmış kod bloğu, parametrelerle veri al, return ile değer ver — modern Python’un ve PyTorch’un (class Net(nn.Module): def forward(self, x): return ...) iskeletidir; saf fonksiyon disiplini JAX jit ve PyTorch torch.compile modern performans araçlarının zeminidir; Mosh’un üç chapter’ında öğrettiği basit def kup(num): return num*num*num, ML eğitim döngüsündeki her def forward(self, x): return self.layer(x)’in çekirdek atasıdır.