---
title: Diziler
source: 'https://academia.sh/tr/kurslar/python-ile-analiz/diziler'
course: 'Python ile Veri Analizi'
language: tr
updated: '2026-08-17T18:08:43+00:00'
license: 'CC BY-SA 4.0'
---

# Diziler

Kursun ölçü birimi kuruluyor: aynı iş (abone başına toplam, genel ortalama, 40 m³ üstü hücre sayısı) iç içe listelerle ve bir dizi arayüzüyle yapılır ve satır sayısı 22'den 2'ye, ayrılan bayt 188.864'ten 30.320'ye (öğe başına 49,96'dan 8,02 bayta) düşerken geçiş sayısı 3'ten 3'e, yani hiç düşmez. Gizlenen karar dizinin boş değeri olmamasıdır: 581 boş hücre sıfırla doldurulduğunda ortalama 26,993180, nöbetçi değerle 26,839476, yalnız dolu hücrelerle 31,895661 m³ çıkar; 40 m³ üstü sayım üç kararda da 1.116'dır. Öğe tipi seçimi 3.780 öğeyi 7.560 ile 30.240 bayt arasında tutar.

Önceki derste ortam sabitlendi ve defter iki makinede aynı sayıyı verir hale geldi. Hesabın
kendisi ise değişmedi: 3.780 hücre iç içe döngülerle tek tek gezildi, her hücre kendi başına bir
nesne olarak tutuldu ve her soru için veri baştan sona yeniden okundu. Bu ders aynı işi bir **dizi
arayüzüyle** yapar.

Ders yalnız bir kolaylık göstermez, kursun **ölçü birimini** kurar. Bundan sonraki her derste iki
sayı yan yana duracak: soyutlamanın kazandırdığı ve soyutlamanın gizlediği. Kazanç burada üç
birimle ölçülür — kaç satır kod, veri üzerinden kaç tam geçiş, kaç bayt. Gizlenen karar ise dizinin
sana sormadan verdiği karardır. Kütüphane çağrılmaz; dizi davranışı standart kitaplıkla
modellenir, çünkü amaç bir aracı taklit etmek değil davranışını ölçülebilir kılmaktır.

- **SH3.** Bir dizi arayüzü üç şeyi birlikte sabitler: **bitişik bellek**, **tek öğe tipi** ve
  **biçim**. Kazanç bu üçlünün sonucudur ve baytta ile çağrı yerindeki satır sayısında görünür;
  veri üzerindeki geçiş sayısında görünmez.
- **SH4.** Dizinin boş değeri yoktur. Eksik bir hücre bir sayıya dönüşmek zorundadır ve hangi
  sayıya dönüştüğü bir karardır. Bu karar bazı özetleri oynatır, bazılarını hiç oynatmaz.

## Aynı İş, İki Yapı

```python
# diziler.py — MODELDIR: dizi arayuzunun uc ozelligi standart kitaplikla yaziliyor:
# bitisik bellek, tek oge tipi, bicim. Kutuphane cagrilmiyor; amac araci taklit
# etmek degil, davranisini olculebilir kilmak. Kume K03'un hazirladigi kurgu kumedir.
import inspect
import sys
from array import array

def uretec(tohum):
    s = tohum & 0xFFFFFFFF
    def sonraki():
        nonlocal s
        s = (1664525 * s + 1013904223) & 0xFFFFFFFF
        return s / 4294967296
    return sonraki

ABONE, DONEM = 1260, 3
r = uretec(20260218)
HAM = [round(4 + r() * 56, 2) for _ in range(ABONE * DONEM)]
r2 = uretec(9110723)
p = [r2() for _ in range(ABONE * DONEM)]
BOS = set(sorted(range(len(p)), key=lambda j: p[j])[:581])
OKUMA = [None if j in BOS else HAM[j] for j in range(ABONE * DONEM)]
TABLO = [OKUMA[i*DONEM:(i+1)*DONEM] for i in range(ABONE)]

GECIS = 0  # veri uzerinden bastan sona bir tam tarama

def elle(t):
    global GECIS
    abone_toplami = []
    for s in t:
        a = 0.0
        for x in s:
            if x is not None:
                a += x
        abone_toplami.append(a)
    genel, n = 0.0, 0
    for s in t:
        for x in s:
            if x is not None:
                genel += x
                n += 1
    ust = 0
    for s in t:
        for x in s:
            if x is not None and x > 40.0:
                ust += 1
    GECIS += 3
    return abone_toplami, genel / n, ust

class Dizi:
    def __init__(self, veri, bicim, tip="d"):
        self.d, self.bicim, self.tip = array(tip, veri), bicim, tip
    @property
    def oge(self):
        return self.bicim[0] * self.bicim[1]
    def eksen_toplami(self, eksen):
        global GECIS
        GECIS += 1
        a, b = self.bicim
        if eksen == 1:
            return [sum(self.d[i*b:(i+1)*b]) for i in range(a)]
        return [sum(self.d[i*b+j] for i in range(a)) for j in range(b)]
    def toplam(self):
        global GECIS
        GECIS += 1
        return sum(self.d)
    def ustunde(self, esik):
        global GECIS
        GECIS += 1
        return sum(1 for x in self.d if x > esik)

def dizi_ile(a):
    return a.eksen_toplami(1), a.toplam() / a.oge, a.ustunde(40.0)

def liste_bayt(t):
    b = sys.getsizeof(t)
    for s in t:
        b += sys.getsizeof(s) + sum(sys.getsizeof(x) for x in s if x is not None)
    return b

DUZ = Dizi([0.0 if x is None else x for x in OKUMA], (ABONE, DONEM))
GECIS = 0
E = elle(TABLO)
ge = GECIS
GECIS = 0
D = dizi_ile(DUZ)
gd = GECIS
satir = lambda f: len(inspect.getsource(f).strip().splitlines())
bl, bd = liste_bayt(TABLO), sys.getsizeof(DUZ.d)

gen = lambda w: lambda h: "".join(str(v).ljust(w[0]) if j == 0 else str(v).rjust(w[j])
                                  for j, v in enumerate(h))
y = gen([20, 20, 16, 10])
print(f"bicim {DUZ.bicim}, oge sayisi {DUZ.oge}, oge tipi 64 bit kesirli, "
      f"bos hucre {len(BOS)}")
print("is: abone basina toplam, genel ortalama, 40 m3 ustu hucre sayisi\n")
print(y(["olcu", "elle yazilan dongu", "dizi arayuzu", "oran"]))
print(y(["satir sayisi", satir(elle), satir(dizi_ile), f"{satir(elle)/satir(dizi_ile):.1f}x"]))
print(y(["gecis sayisi", ge, gd, f"{ge/gd:.1f}x"]))
print(y(["ayrilan bayt", bl, bd, f"{bl/bd:.1f}x"]))
print(y(["oge basina bayt", f"{bl/DUZ.oge:.2f}", f"{bd/DUZ.oge:.2f}", f"{bl/bd:.1f}x"]))
print(f"\nayni is, iki sonuc: ortalama elle {E[1]:.6f} m3, dizi arayuzuyle {D[1]:.6f} m3; "
      f"40 m3 ustu hucre iki yolda da {E[2]}")
```

```
bicim (1260, 3), oge sayisi 3780, oge tipi 64 bit kesirli, bos hucre 581
is: abone basina toplam, genel ortalama, 40 m3 ustu hucre sayisi

olcu                  elle yazilan dongu    dizi arayuzu      oran
satir sayisi                          22               2     11.0x
gecis sayisi                           3               3      1.0x
ayrilan bayt                      188864           30320      6.2x
oge basina bayt                    49.96            8.02      6.2x

ayni is, iki sonuc: ortalama elle 31.895661 m3, dizi arayuzuyle 26.993180 m3; 40 m3 ustu hucre iki yolda da 1116
```

Üç ölçünün tanımı kurs boyunca sabit kalır. **Satır sayısı** çağrı yerinde yazılan kod satırıdır
ve koddan okunur, elle sayılmaz. **Geçiş sayısı** veri üzerinden baştan sona yapılan tam tarama
sayısıdır; modelde her tarama bir sayacı bir artırır, dolayısıyla iddia edilen değil ölçülen bir
sayıdır. **Ayrılan bayt** veriyi tutan yapının kendisinin ve içindeki nesnelerin kapladığı yerdir.
Üçü de koşumdan koşuma değişmez; süre değişir, bu yüzden süre ölçülmez. Bir soyutlamanın kazancı
bu üç sayıdan hangilerini düşürdüğüyle, bedeli ise hangilerini düşürmediğiyle tanımlanır.

Tablonun ilk satırı beklenen kazançtır. Aynı üç soru elle yazıldığında 22 satır tutuyor, dizi
arayüzünde 2 satır. Fark bir yazım kısalığı değil: elle yazılan sürümde eksik hücre denetimi üç
kez tekrarlanıyor, döngü sınırları üç kez yazılıyor ve her tekrarda bunlardan birini atlama
ihtimali var. Soyutlama bu üç tekrarı tek bir yere taşıyor.

Üçüncü satır ikinci kazançtır ve nedeni **biçim** ile **öğe tipi** kararının bir kez verilmiş
olmasıdır. İç içe listelerde 3.780 sayının her biri kendi başına bir nesnedir; nesnenin kendisi
yaklaşık 24 bayt, ona işaret eden gösterici 8 bayt, satırı tutan 1.260 küçük listenin her biri
ayrıca yer kaplar. Toplam 188.864 bayt, öğe başına 49,96. Dizide 3.780 sayı bitişik bir bellek
bloğunda, öğe başına tam 8 bayt duruyor ve biçim yalnız iki tamsayıdan ibaret: 30.320 bayt,
öğe başına 8,02. Oran 6,2 kat.

İkinci satır ise kazanç değil. Geçiş sayısı iki yolda da **3**, çünkü sorulan soru üç tane ve her
soru veriyi baştan sona bir kez okuyor. Dizi arayüzü döngüyü çağrı yerinden kaldırır, veriden
kaldırmaz. Bu kursun en sık yanlış okunan sayısıdır: iki satır kod yazıldığı için tek geçiş
yapıldığı sanılır. Zincirlenen her çağrı kendi geçişini ekler ve bir sonraki dersin ölçtüğü şey
tam olarak budur. Elle yazılan sürümde bu üç geçişi tek geçişe indirmek üç döngüyü tek döngüde
birleştirmek demektir ve bunun yazılması iki satır tutar; dizi arayüzünde aynı birleştirmeyi
yapmak için çağrı zincirinden çıkıp döngüye geri dönmek gerekir. Kısalık ile geçiş sayısı burada
birbirinin karşısındadır.

Son satır ise gizlenen kararı işaret ediyor. Aynı iş, aynı veri, iki farklı ortalama: 31,895661
ile 26,993180 m³. Aradaki 4,90 m³ bir hesap hatası değil, dizinin yapısından doğan bir karardır.

## Biçim ve Eksen

Modeldeki `Dizi` sınıfı iki alan taşıyor ve ikisinin ayrı durması dizi arayüzünün en belirleyici
özelliğidir. `d` alanı 3.780 sayıyı tek bir düz blokta tutar; `bicim` alanı yalnız iki tamsayıdan
ibarettir ve o düz bloğun nasıl okunacağını söyler. Veri iki boyutlu değildir — **okunuşu** iki
boyutludur.

Bu ayrımın doğrudan sonucu, biçim değiştirmenin veriyi hiç kopyalamamasıdır. (1260, 3) yerine
(3, 1260) yazmak 30.240 baytın hiçbirini kımıldatmaz, yalnız `eksen_toplami` işlevindeki dilim
sınırlarını değiştirir. Bu ucuzluk soyutlamanın en kullanışlı yanıdır ve aynı zamanda en sessiz
yanıdır: yanlış bir biçim bir hata üretmez, yalnız başka bir sayı üretir.

**Eksen** o biçim içindeki bir yöndür ve modeldeki numaralandırma soldan sağadır: eksen 0 abone
yönü, eksen 1 dönem yönüdür. `eksen_toplami(1)` her abonenin üç dönemini toplar ve 1.260 değer
verir; `eksen_toplami(0)` her dönemin bütün abonelerini toplar ve 3 değer verir. İkisi de "toplam"
adını taşır, ikisi de aynı 102.034,22 m³'ü paylaştırır, ama biri abone davranışını, öteki dönem
davranışını anlatır. Elle yazılan döngüde hangi yönde toplandığı döngü satırlarından okunur; dizi
arayüzünde tek bir tamsayıdan okunur ve o tamsayı çoğu zaman varsayılan olarak bırakılır. Bu ders
kapsamında eksen açıkça yazılıyor; bir sonraki derse kadar tutulacak kural şudur: **eksen
yazılmayan bir toplulaştırma, yönü seçilmemiş bir toplulaştırmadır.**

## Dizinin Boş Değeri Yoktur

```python
# bos.py — MODELDIR: dizinin "bos" degeri yok. 581 bos hucre bir sayiya donusmek
# zorunda ve hangi sayiya donustugu bir karar. Uc karar, uc ortalama.
KARAR = [
    ("sifirla doldur", lambda v: [0.0 if x is None else x for x in v]),
    ("nobetci -1", lambda v: [-1.0 if x is None else x for x in v]),
    ("yalniz dolu hucre", lambda v: [x for x in v if x is not None]),
]
z = gen([24, 12, 16, 12])
print(z(["581 bos hucrenin yeri", "oge sayisi", "ortalama (m3)", "40 m3 ustu"]))
for ad, f in KARAR:
    a = Dizi(f(OKUMA), (len(f(OKUMA)), 1))
    print(z([ad, a.oge, f"{a.toplam()/a.oge:.6f}", a.ustunde(40.0)]))

TIP = [("16 bit tamsayi", "h"), ("32 bit tamsayi", "i"),
       ("32 bit kesirli", "f"), ("64 bit kesirli", "d")]
LITRE = [int(round((0.0 if x is None else x) * 1000)) for x in OKUMA]
z2 = gen([18, 10, 10, 30])
print("\n" + z2(["oge tipi", "bayt/oge", "3780 oge", "temsil araligi"]))
for ad, t in TIP:
    b = array(t).itemsize
    aralik = (f"-{2**(8*b-1)} .. {2**(8*b-1)-1}" if t in ("h", "i")
              else ("7 anlamli basamak" if t == "f" else "15 anlamli basamak"))
    print(z2([ad, b, b * DUZ.oge, aralik]))

TOPLAM = DUZ.toplam()
kucuk = array("f", [TOPLAM])[0]
print(f"\nen buyuk okuma {max(LITRE)} litre; 16 bit tamsayi bu degeri tasimaz")
print(f"kumenin toplami {TOPLAM:.2f} m3; 32 bit kesirli tipte {kucuk} olarak tutulur, "
      f"fark {abs(kucuk-TOPLAM):.5f} m3 ve 01. dersin 0,0005 m3 esiginin ustunde")
```

```
581 bos hucrenin yeri     oge sayisi   ortalama (m3)  40 m3 ustu
sifirla doldur                  3780       26.993180        1116
nobetci -1                      3780       26.839476        1116
yalniz dolu hucre               3199       31.895661        1116

oge tipi            bayt/oge  3780 oge                temsil araligi
16 bit tamsayi             2      7560               -32768 .. 32767
32 bit tamsayi             4     15120     -2147483648 .. 2147483647
32 bit kesirli             4     15120             7 anlamli basamak
64 bit kesirli             8     30240            15 anlamli basamak

en buyuk okuma 60000 litre; 16 bit tamsayi bu degeri tasimaz
kumenin toplami 102034.22 m3; 32 bit kesirli tipte 102034.21875 olarak tutulur, fark 0.00125 m3 ve 01. dersin 0,0005 m3 esiginin ustunde
```

Üç satır üç savunulabilir karardır ve ortalamayı 26,839476 ile 31,895661 m³ arasında oynatır.
**Sıfırla doldurmak** eksik okumayı "hiç su kullanılmadı" saymaktır ve payı büyütmeden paydayı
büyüttüğü için ortalamayı 4,90 m³ düşürür. **Nöbetçi değer** eksik hücreyi işaretlemek için
seçilir, ama işaretin dışlanması unutulursa toplamdan 581 m³ düşer ve ortalama daha da iner.
**Yalnız dolu hücre** kararı payda olarak 3.199'u kullanır ve önceki kursun ölçtüğü sayıyı verir.
Üçünün de bir gerekçesi vardır; gerekçesi olmayan tek şey, kararın hiç yazılmamasıdır.

Dördüncü sütun bu kararın nerede görünmediğini gösteriyor. **40 m³ üstü hücre sayısı üç kararda da
1.116'dır**, çünkü üç doldurma değeri de eşiğin altındadır. Bir denetim yalnız bu sayıya bakıyorsa
üç kararı birbirinden ayıramaz. Kararın oynattığı sayı ile kararı görünmez kılan sayı aynı
tablodadır ve hangisinin rapor edildiği kararın kendisi kadar önemlidir.

Elle yazılan sürümün bu kararı vermek zorunda kalmadığına dikkat etmek gerekir. İç içe listelerde
boş hücre `None` olarak durur; bu değer bir sayı değildir, toplamaya girmez ve `is not None`
denetimi onu döngünün içinde açıkça dışarıda bırakır. Karar oradadır ama **görünürdür**, çünkü her
döngüde tek tek yazılmıştır. Dizide karar hiç yazılmaz; diziyi kuran satırda bir doldurma değeri
seçilir ve o değer, bir daha hiç anılmadan, bütün özetlere karışır. Soyutlamanın gizlediği şey
kararın kendisi değil, kararın **nerede alındığıdır**.

Alt tablo öğe tipi kararını ölçüyor. Aynı 3.780 öğe, seçilen tipe göre 7.560 ile 30.240 bayt
arasında yer tutar; dörde bir fark bellekten değil, temsil aralığından ödenir. En büyük okuma
60.000 litredir ve 16 bit tamsayının 32.767 sınırını aşar — bu tipi seçmek dört kat bellek kazancı
değil, sessiz bir taşmadır. 32 bit kesirli tip taşmaz ama yaklaşık yedi anlamlı basamak tutar;
kümenin 102.034,22 m³ toplamı sekiz anlamlı basamak gerektirdiği için 102.034,21875 olarak
saklanır. Fark 0,00125 m³ ve önceki dersin 0,0005 m³ eşiğinin üstünde, yani bu tip seçimi tek
başına iki koşumu farklı kılmaya yeter.

## Özet

- Bir dizi arayüzü bitişik belleği, tek öğe tipini ve biçimi birlikte sabitler; biçim burada
  (1260, 3) ve öğe sayısı 3.780'dir.
- Aynı üç soru elle 22 satır, dizi arayüzünde 2 satır tutar; ayrılan bayt 188.864'ten 30.320'ye,
  öğe başına 49,96'dan 8,02 bayta iner.
- Geçiş sayısı iki yolda da 3'tür: soyutlama döngüyü çağrı yerinden kaldırır, veriden kaldırmaz.
- Dizinin boş değeri olmadığı için 581 boş hücre bir sayıya dönüşür; ortalama sıfır doldurmada
  26,993180, nöbetçi değerde 26,839476, yalnız dolu hücrede 31,895661 m³ çıkar.
- Aynı üç karar 40 m³ üstü hücre sayısını hiç değiştirmez (1.116); öğe tipi seçimi ise 3.780 öğeyi
  7.560 ile 30.240 bayt arasında tutar ve 16 bit tamsayı 60.000 litrelik okumayı taşımaz.

## Sonraki Adım

Ölçü birimi kuruldu ve üç sayıdan biri beklenenin dışında çıktı: geçiş sayısı düşmedi. Sonraki
ders tam bu sayıyı ele alır. Aynı türetme işi tek bir döngüde bir geçişle yapılabilir ya da
vektörleştirilmiş çağrıların zinciri olarak yazılabilir; ikinci yol her çağrıda bir geçiş ve bir
ara dizi ekler. Aynı ders vektörleştirmenin sessizce verdiği iki kararı da sayar: öğe tipinin
yükseltilmesi ve dar bir tipte taşma. Bu dersin son tablosunda 16 bit tamsayının 60.000 litrelik
okumayı taşımadığı görüldü; sonraki ders bu sınırın aşıldığında ne olduğunu ölçer.
