5  Listeler ve Tuple’lar

[...] ve (...) — NumPy/PyTorch tensor’ların atası

NotBölüm bilgisi

5.1 Bu Derste Ne Var?

Şimdiye kadar tek veriyle çalıştık: bir ad, bir yaş, iki sayı. Ders 4’te bir grup veriyi tek bir değişkende saklamayı öğreneceksin. Bu, Python’un (ve genel programlamanın) en temel adımlarından biri — ve ML’e açılan en dolaysız köprü.

flowchart LR
    A["📦 list [1,2,3]"] --> B["İndeksleme & dilimleme"]
    A --> C["Methods:<br/>.append, .extend, .sort"]
    D["📌 tuple (1,2,3)"] --> E["Değişmez"]
    A --> F["💡 Aynı [i] syntax"]
    D --> F
    F --> G["➡️ NumPy ndarray"]
    G --> H["➡️ PyTorch Tensor"]
    D --> I["x.shape = (32,3,224,224)"]

    style A fill:#e3f2fd,stroke:#3776ab,stroke-width:2px
    style D fill:#fff3e0,stroke:#f57c00,stroke-width:2px
    style H fill:#fce4ec,stroke:#c2185b,stroke-width:3px
Şekil 5.1: Ders 4’ün akış haritası — list/tuple’dan tensor evrenine

Dersin beş parçası:

  1. Listeler (list).[1, 2, 3], ["Kevin", "Karen", "Jim"].
  2. Erişim ve dilimleme.friends[0], friends[-1], friends[1:3].
  3. List metodları..append, .insert, .remove, .sort, .copy, vb.
  4. Tuple’lar.(3, 5). Değişmez (immutable).
  5. List vs Tuple. — Ne zaman hangisi?
İpucuBuilder Notu — Bu Dersin ML Köprüleri
  • List = NumPy ndarray = PyTorch Tensor’ın atası. En derin köprü. Köşeli parantez syntax’ı tüm bu evrenlerde aynı.
  • 0-tabanlı indexing = evrensel sözleşme. Mosh’un friends[0], NumPy/tensor’da x[0] ile aynı. friends[-1] “son eleman” deyimi.
  • Slicing [a:b] tüm Python sequence’lerinde aynı. x[1:5, :, ::2] PyTorch’ta normal; Mosh’un friends[1:3]’ü bu syntax’ın 1-boyutlu hali.
  • .append() = batch oluşturma habercisi. ML’de losses = [] + losses.append(loss.item()) her eğitim döngüsünde.
  • .sort() + sorted(). ML’de top-k indeksi, scoring, ranking için her gün. torch.sort aynı fikir.
  • .extend() = numpy.concatenatetorch.cat. Birden fazla parçayı birleştirme.
  • Tuple immutable = config + shape. Tensor shape her zaman tuple: x.shape == (32, 3, 224, 224). Configuration veri demeti, sabit kalır.
  • Tuple unpacking = ML günlük rutini. batch, ch, h, w = x.shape, logits, hidden = model(x).

5.2 List Nedir, Neden Var?

“liste aslında sadece python içinde kullanabileceğimiz bir yapı. bilgi listelerini saklamak için bir sürü farklı veri değerlerini bir listeye koyabiliriz” — Mosh (Türkçe dublaj), 1:03:26

5.2.1 Motivasyon

Kötü yol — tek tek değişkenler:

friend1 = "Kevin"
friend2 = "Karen"
friend3 = "Jim"
friend4 = "Oscar"
# ... bin tane mi yazacağız?

İyi yol — list:

friends = ["Kevin", "Karen", "Jim", "Oscar"]

Tek değişken, tüm değerleri kapsar. Eklemek, silmek, sıralamak — hepsi tek bir yer üzerinde.

5.2.2 Syntax

liste_adi = [eleman1, eleman2, eleman3, ...]
friends = ["Kevin", "Karen", "Jim", "Oscar"]    # string'ler
numbers = [42, 7, 100, -3]                       # int'ler
prices = [9.99, 24.50, 0.01]                     # float'lar
flags = [True, False, True, True]                # boolean'lar
empty = []                                       # bos liste

5.2.3 List, ndarray, Tensor — Akrabalar

İpucuBuilder Notu — Üç Yapı, Aynı Sezgi

Üç yapı da “sıralı dizi”:

# Python list
friends = ["Kevin", "Karen", "Jim"]

# NumPy ndarray (vektorlu, ayni tip)
import numpy as np
x = np.array([1.0, 2.0, 3.0])             # shape: (3,), dtype: float64

# PyTorch Tensor (GPU + autograd)
import torch
y = torch.tensor([1.0, 2.0, 3.0])         # shape: (3,), dtype: float32

# Ayni syntax tümünde:
friends[0]   # 'Kevin'
x[0]         # 1.0
y[0]         # tensor(1.)

friends[1:3] # ['Karen', 'Jim']
x[1:3]       # array([2., 3.])
y[1:3]       # tensor([2., 3.])

len(friends) # 3
len(x)       # 3
len(y)       # 3

Farklar (özet):

Özellik list ndarray Tensor
Türdeşlik isteğe bağlı zorunlu zorunlu
Vektorlu işlem yok var var
GPU yok yok var
Autograd yok yok var
Tipik kullanım genel bilimsel hesap derin öğrenme

5.3 Erişim — Indexing ve Slicing

5.3.1 Tek Eleman

“bu listenin içindeki öğelerin her biri belirli bir indeks ve endeks aslında sıfırdan başlıyor” — Mosh (Türkçe dublaj), 1:06:36

friends = ["Kevin", "Karen", "Jim", "Oscar"]

friends[0]    # 'Kevin'    (ILK = index 0)
friends[3]    # 'Oscar'    (SON = index 3)
friends[-1]   # 'Oscar'    (sondan)
friends[-2]   # 'Jim'
friends[100]  # IndexError

5.3.2 Slicing — [a:b]

friends[1:3]   # ['Karen', 'Jim']      (1'den 3'e, 3 HARIC)
friends[:2]    # ['Kevin', 'Karen']
friends[2:]    # ['Jim', 'Oscar']
friends[:]     # tam kopya

“Exclusive end” sözleşmesi: [a:b] index b’yi dahil etmez. Python, NumPy, PyTorch — hepsinin standardı.

5.3.3 Step ile Adım

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

nums[0:10:2]   # [0, 2, 4, 6, 8]   (2'şer atla)
nums[::-1]     # [9, 8, 7, ..., 0] (TERS)

nums[::-1] Python’un meşhur “ters çevirme” deyimi.

5.3.4 Slicing’in ML Eki

İpucuBuilder Notu — 4-Boyutlu Slicing

NumPy ve PyTorch slicing birebir aynı syntax’la çalışır, ama n-boyutlu:

import torch
x = torch.randn(32, 3, 224, 224)   # batch=32, kanal=3, H=224, W=224

x[0]                  # ilk ornek: (3, 224, 224)
x[-1]                 # son ornek
x[:5]                 # ilk 5 ornek: (5, 3, 224, 224)
x[:, 0, :, :]         # her ornek - sadece R kanali: (32, 224, 224)
x[:, :, 100:150, :]   # tum orneklerin y=100-149 satirlari
x[::2, ::2, ::2, ::2] # her boyutta 2'şer atla

Mosh’un friends[1:3]’ü öğrendiğinde, yukarıdaki 4-boyutlu tensor slicing’in syntax’ı otomatik elinde. Bu Python’un en güçlü tasarım kararlarından biri.

Şekil 5.2: Slicing tüm sequence tiplerinde aynı syntax: string, list, ndarray, tensor

5.4 Mutation — List Değişebilir

String’ler immutable’dı (Ders 2): phrase.upper() yeni string döndürür. List mutable:

friends = ["Kevin", "Karen", "Jim", "Oscar"]
friends[1] = "Mike"
print(friends)
# ['Kevin', 'Mike', 'Jim', 'Oscar']
UyarıBuilder Notu — Tensor Inplace Ops

ML’de requires_grad=True olan tensor’larda inplace mutation autograd grafiğini bozabilir:

w = torch.randn(10, requires_grad=True)
w[0] = 0   # UYARI: RuntimeError veya silent bug riski

Bu yüzden ML kodunda x.detach()[0] = 0 veya with torch.no_grad(): w[0] = 0 kullanılır. Mosh’un basit friends[1] = "Mike" mutation’ı rahat, ama tensor’larda dikkat.

5.5 List Metodları

5.5.1 .append(x) — Sona Ekle (EN YAYGIN)

friends = ["Kevin", "Karen", "Jim"]
friends.append("Oscar")
# ['Kevin', 'Karen', 'Jim', 'Oscar']

ML eğitim döngüsünde her epoch:

losses = []
for epoch in range(100):
    loss = train_one_epoch()
    losses.append(loss)

5.5.2 .insert(i, x) — Belirli Pozisyona Ekle

friends = ["Kevin", "Karen", "Jim"]
friends.insert(1, "Kelly")
# ['Kevin', 'Kelly', 'Karen', 'Jim']

5.5.3 .extend(other) — Listeyi Listeye Ekle

friends = ["Kevin", "Karen"]
new_friends = ["Jim", "Oscar"]
friends.extend(new_friends)
# ['Kevin', 'Karen', 'Jim', 'Oscar']

.append vs .extend farkı:

# Append - tek element olarak:
[1, 2].append([3, 4])    # [1, 2, [3, 4]]    iç liste!

# Extend - elemanları teker teker:
a = [1, 2]
a.extend([3, 4])         # [1, 2, 3, 4]      düz

5.5.4 .remove(x), .pop(), .clear()

friends.remove("Jim")     # ilk eşleşeni sil
last = friends.pop()      # sondan çıkar ve döndür
friends.clear()           # hepsini sil

5.5.5 .index(x), .count(x)

friends.index("Karen")    # 1 (yoksa ValueError)
[1, 2, 2, 3].count(2)     # 2

5.5.6 .sort() vs sorted(...)

nums = [42, 7, 100, -3]
nums.sort()               # YERINDE değiştirir
# nums artik [-3, 7, 42, 100]

# Non-mutation alternative:
nums2 = sorted([42, 7, 100, -3])    # yeni liste
nums2.sort(reverse=True)             # büyükten küçüğe

5.5.7 .copy() — Kopya (kritik!)

# YANLIS - referans paylasimi:
a = [1, 2, 3]
b = a            # AYNI liste
b.append(4)
print(a)         # [1, 2, 3, 4]  ← a da değişti!

# DOGRU:
a = [1, 2, 3]
b = a.copy()     # yeni liste
b.append(4)
print(a)         # [1, 2, 3]     ← a değişmedi

5.5.8 .append() + .extend() ML’de

İpucuBuilder Notu — Topla, Birleştir
# Eğitim metrikleri:
train_losses = []
for epoch in range(EPOCHS):
    train_losses.append(train_one_epoch())

# Tensor versiyonu:
import torch
batch_logits = []
for batch in dataloader:
    batch_logits.append(model(batch))

all_logits = torch.cat(batch_logits, dim=0)   # extend gibi - tum tensor'lari birlestir

torch.cat() Mosh’un .extend()’inin tensor versiyonu — birden fazla tensoru tek tensora birleştirir. numpy.concatenate() ile aynı mantık.

5.6 Tuple — Değişmez Liste

“Bir tupel aslında bir listeye çok benzer […] fakat Bir tupel listelerden bazı önemli farklılıklar vardır” — Mosh (Türkçe dublaj), 1:19:17

5.6.1 Sentaks

coords = (3, 5)
print(coords)       # (3, 5)
print(coords[0])    # 3   (indexing aynı)
print(len(coords))  # 2

Liste [...], tuple (...). Tek karakter fark — büyük anlam farkı.

5.6.2 Immutability — Hata Verir

coords = (3, 5)
coords[0] = 10   # TypeError: 'tuple' object does not support item assignment
coords.append(7) # AttributeError: 'tuple' has no attribute 'append'

Tuple’da mutation yok. Sadece okuma: indexing, slicing, len(), .index(), .count().

5.6.3 Niye Immutable?

  1. Niyet bildirimi. “Bu veri sabit kalacak” demek.
  2. Hash’lenebilir → dict key olabilir. Liste dict anahtarı olamaz; tuple olabilir (Ders 7).
  3. Performans. Bellek olarak biraz daha verimli.

5.6.4 Tuple Unpacking — Çok Güçlü

nokta = (3, 5)
x, y = nokta       # x=3, y=5

# Coklu return:
ad, soyad = ("Deniz", "Demir")

# Tek satirda swap:
a, b = 1, 2
a, b = b, a        # a=2, b=1

C/Java/JS’de int temp = a; a = b; b = temp; yazmak zorundasın; Python: tek satır.

5.7 Tuple = ML Shape + Config

ÖnemliBuilder Notu — Tensor Shape ve Unpacking

Tensor shape her zaman tuple:

import torch
x = torch.randn(32, 3, 224, 224)
print(x.shape)         # torch.Size([32, 3, 224, 224])  ← tuple-like
print(x.shape[0])      # 32

# Unpacking - çok yaygın:
batch, channels, height, width = x.shape

Shape niye tuple? Çünkü değişmez — bir tensor yaratıldıktan sonra shape’i değiştirmek (tensor.reshape(...)) yeni tensor yaratır. Python’un “bu sabit kalacak” sinyali tam yerinde.

Model output unpacking:

# PyTorch transformer benzeri model:
def forward(x):
    logits = ...
    hidden_states = ...
    attention_weights = ...
    return logits, hidden_states, attention_weights   # 3-tuple

# Kullanim:
logits, hidden, attn = model(x)   # unpacking

dict key olarak tuple:

image_cache = {}
image_cache[(3, 224, 224)] = preprocessed_imagenet
image_cache[(1, 28, 28)] = preprocessed_mnist

ML kodunda tuple her yerde.

5.8 List vs Tuple Karar Matrisi

Soru Cevap Hangisi
Veri değişecek mi? EVET list
Veri sabit mi? EVET tuple
Dict key olarak? EVET tuple (zorunlu)
Birden fazla değer döndürme? EVET tuple (idiomatic)
Veri “kayıt” mi? EVET tuple
Veri “koleksiyon” mu? EVET list
# List - değişecek:
friends = ["Kevin", "Karen"]      # yeni arkadaş eklenebilir
losses = []                       # her epoch loss

# Tuple - sabit:
coords = (3, 5)                   # geometrik nokta
rgb = (255, 0, 0)                 # kırmızı RGB
days = ("Pzt", "Sal", "Car", "Per", "Cum", "Cmt", "Paz")

5.9 Bu Dersin Özeti

  1. list[...] sıralı + değişebilir.
  2. Indexingfriends[0] ilk (0-tabanlı), friends[-1] son.
  3. Slicingfriends[1:3] (3 hariç). [::-1] ters.
  4. Mutationfriends[1] = "Mike". List mutable, string değildi.
  5. .append(x) — sona ekle (en yaygın).
  6. .extend(other)numpy.concatenate / torch.cat’in atası.
  7. .sort() vs sorted() — yerinde vs yeni liste.
  8. tuple(...) sıralı + değişmez.
  9. Tuple unpackingbatch, ch, h, w = x.shape.
ÖnemliTek Bir Cümle

Listenin köşeli parantezi ([1,2,3]) ile tuple’ın parantezi ((1,2,3)) arasındaki tek fark — mutability — modern ML kodunun en derin tasarım kararıdır: değişen veri liste’dir (loss history, batch buffer), sabit veri tuple’dır (tensor shape, config sabitleri); aynı [i] ve [a:b] syntax’ı string’den 4-boyutlu PyTorch tensorlarına kadar hepsinde çalışır.

5.10 Egzersizler

Egzersiz 1. En sevdiğin beş şehri liste, sonra:

sehirler = ["Istanbul", "Ankara", "Izmir", "Antalya", "Bursa"]

# (a) Tum listeyi yazdır
# (b) İlk ve son şehri tek satirda
# (c) Ortadaki şehir (len kullanarak)
# (d) sorted ile sırala, orijinal değişmesin

Egzersiz 2. Alışveriş listesi:

liste = []
# (a) "Ekmek", "Sut", "Yumurta" append ile
# (b) Basina "Kahve" insert ile
# (c) "Sut" remove
# (d) Yazdır → ['Kahve', 'Ekmek', 'Yumurta']

Egzersiz 3. Slicing tahmin et, sonra çalıştır:

nums = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
print(nums[:5])
print(nums[5:])
print(nums[2:7])
print(nums[::2])
print(nums[::-1])
print(nums[1:8:2])
print(nums[-3:])

Egzersiz 4. İki noktanın mesafesini tuple unpacking ile:

import math
p1 = (3, 4)
p2 = (7, 1)
x1, y1 = p1
x2, y2 = p2
mesafe = math.sqrt((x2-x1)**2 + (y2-y1)**2)
print(f"Mesafe: {mesafe:.2f}")    # 5.00

Egzersiz 5. (Builder eksen — tensor shape simülasyonu)

def get_tensor_shape():
    return (32, 3, 224, 224)   # batch, channels, height, width

shape = get_tensor_shape()
batch, channels, height, width = shape

print(f"Batch boyutu: {batch}")
print(f"Kanal sayisi: {channels}")
print(f"Goruntu boyutu: {height}x{width}")
print(f"Toplam piksel: {batch * channels * height * width:,}")
# 4,816,896 piksel

PyTorch model çıktısı işlerken her gün bu pattern.

5.11 Sonraki Ders İçin Hazırlık

Ders 5: Fonksiyonlar

Şu ana kadar yazdığımız tüm kod düz, satır-satır akan kod. Ders 5’te kodu yeniden kullanılabilir bloklara ayırmayı öğreneceğiz. PyTorch’taki nn.Module.forward(self, x)’in dolaysız atası.

  • Mosh’un Ch 14-15’ini izle (1:24:21-1:40:09, ~16 dk).
  • Şu cümleyi içselleştir: “Fonksiyon = adlandırılmış kod bloğu = yeniden kullanılabilir hesaplama.”
İpucuBu dersten tek bir şey alıp gideceksen

Liste ([...]) değişebilir, tuple ((...)) değişmez — bu tek mutability farkı modern ML kodunun en derin tasarım kararıdır; aynı [i] ve [a:b] syntax’ı string’den 4-boyutlu PyTorch tensor’una kadar her yerde çalışır; Mosh’un friends.append()’i ML’in günlük losses.append(loss.item())’inin atası, (coords) ise PyTorch’taki x.shape’in geometrik akrabasıdır.