---
title: 'Paket Yapısı'
source: 'https://academia.sh/tr/kurslar/python-veri-yapilari/paket-yapisi'
course: 'Veri Yapıları ve Fonksiyonel Araçlar'
language: tr
updated: '2026-08-17T18:10:26+00:00'
license: 'CC BY-SA 4.0'
---

# Paket Yapısı

Aynı kısa ad göreli yazımda komşuya, mutlak yazımda köke çözülür ve iki ayrı nesne verir; tek bir alt modül isteği beş gövde koşturur ve beş modül nesnesi önbelleğe yazar.

Önceki ders modülleri düz bir listede aradı: her kaynak, arama yolundaki bir dizinin
doğrudan içindeydi ve adları tek parçaydı. O düzende iki dosyanın aynı adı taşıması bir
çakışmaydı ve kazananı yalnızca sıra belirliyordu. Kod büyüdüğünde bu düzen yetmez; aynı işi
yapan dosyalar birbirine yakın durmak, aynı kısa adı **farklı bağlamlarda** taşımak ister.

**Paket (package)**, dizinlerin ad alanına katıldığı düzendir: bir dizin ve içindeki
`__init__.py` dosyası birlikte bir modül nesnesi verir, ve o dizinin içindekiler noktayla
ona bağlanır. Bu, adı iki parçalı yapar — bir yolu ve bir kısa adı olur. Dersin sorusu şudur:
aynı kısa ad iki ayrı düzeyde varken, **göreli** ve **mutlak** yazım hangi nesneye çözülür,
ve tek bir istek kaç gövde koşturur?

## Dizin Nasıl Modül Olur

Bir paket, içinde `__init__.py` bulunan dizindir. O dosya paketin **gövdesidir** ve paket ilk
kez istendiğinde bir kez koşar; boş olması da bir seçenektir, o zaman gövde hiçbir ad
bağlamaz ama modül nesnesi yine var edilir. Paketin içindeki dosyalar ve alt dizinler onun
**alt modülleri** ve **alt paketleridir**.

Noktalı bir ad soldan sağa çözülür ve her düzey ayrı bir modül nesnesidir. `paket.alt.arac`
isteği tek bir nesne değil, üç nesne gerektirir: `paket`, `paket.alt` ve `paket.alt.arac`.
Üçü de ayrı ayrı önbelleğe yazılır, üçünün gövdesi de sırayla koşar. Bu, önceki dersin
kuralının doğrudan sonucudur — her ad kendi kaydını alır.

Çözülen her düzey, bir üstünde **öznitelik olarak da bağlanır**. `paket.alt` içe
aktarıldıktan sonra `paket` modül nesnesinin sözlüğünde `alt` adı vardır ve o ad,
önbellekteki `paket.alt` nesnesinin **aynısına** bağlıdır. Noktalı erişimin çalışma biçimi
budur: nokta bir arama yolu araması değil, bir öznitelik okumasıdır.

## İki Yazım, İki Başlangıç Noktası

Aynı alt modüle iki yoldan ulaşılır. **Mutlak** yazım adı **kökten** başlatır: adın ilk
parçası arama yolunda aranır ve zincir oradan çözülür. **Göreli içe aktarım (relative
import)** ise adı **isteği yapan modülün paketinden** başlatır; baştaki nokta "bulunduğum
paket", iki nokta "bir üstteki paket" demektir.

İkisi aynı harfleri taşıyan iki ayrı adres üretir. Bir paketin kökünde `arac` adlı bir modül,
alt paketinde de `arac` adlı başka bir modül varsa, alt paketin içinden yazılan göreli istek
**komşudakini**, mutlak istek **kökteki** modülü verir. Adlar aynıdır; çözüldükleri nesneler
ayrıdır.

Göreli içe aktarımın bir koşulu vardır: isteği yapan modülün bir pakete **ait** olması. Bir
paketin içinde olmayan bir modül için "bulunduğum paket" diye bir şey yoktur ve istek
çözülemez. Ölçüm bu durumu da sınıyor.

## Paketin Gövdesi Kimin Faturası

`__init__.py` bir paketin kapısıdır ve pakete ait **herhangi** bir modül istendiğinde koşar.
Bu, oraya yazılanın bedelini paketin bütün kullanıcılarına ödettiği anlamına gelir. İki
yaygın yazım vardır ve aralarındaki fark ölçülebilir.

**Sade** yazımda `__init__.py` yalnız paketin kendi adlarını bağlar, alt modülleri içe
aktarmaz; kullanıcı hangi alt modülü istiyorsa onu ayrıca yazar. **Peşin** yazımda
`__init__.py` alt modülleri kendisi içe aktarır ve onların adlarını paket düzeyine taşır;
kullanıcı tek bir addan hepsine ulaşır. İkincisi kısa yazım kazandırır ama tek bir yaprağı
isteyen kullanıcıya **bütün** kardeşlerin gövdesini koşturur. Ölçümün son bölümü aynı tek
yaprak isteğini iki yazımda karşılaştırıyor.

## Bir İstek Kaç Gövde Koşturur

İçe aktarmanın bir var etme işi olduğu önceki derste ölçüldü. Paketlerde bu sayı **zincirin
uzunluğuyla** büyür ve zincirin bir tarafı da içe aktarılan modülün kendi isteklerinden
gelir. Bir alt modül, gövdesinde başka modüller içe aktarıyorsa onlar da aynı istekte koşar.
Ölçüm, tek bir isteğin koşturduğu gövdeleri **koşum sırasıyla** yazıyor.

Ölçümün varsayımları:

- **MP11** — Ölçüm depoya dosya bırakmaz; paket ağacı geçici bir dizinde üretilir, iş bitince
  silinir ve **dizinin yolu basılmaz.**
- **MP12** — Koşan gövdeler, her gövdenin ortak bir listeye kendi adını eklemesiyle sayılır;
  sayan taraf koşan modülün kendisidir ve liste **koşum sırasını** korur.
- **MP13** — Kök ve alt pakette **aynı kısa adı** taşıyan iki modül vardır; ikisi yalnız
  modül düzeyindeki bir adın değeriyle ayrılır.
- **MP14** — Göreli ve mutlak istek, ölçülen üçüncü bir modülün gövdesinden yapılır; iki
  sonuç o modülün sözlüğünden okunur.
- **MP15** — Hangi adın bağlandığı ayrı bir ad alanı sözlüğünde ölçülür; iki tanımlı ad
  dışındaki adlar ayıklanır.
- **MP16** — Pakete ait olmayan bir modülde göreli istek denenir; kâhin istisnanın **sınıf
  adıdır**, ileti metni değil.
- **MP17** — Ölçüm bittiğinde eklenen yol girdisi ve bütün önbellek kayıtları geri alınır.
- **MP18** — Sade ve peşin yazım **aynı ağaç biçimini** taşır: bir paket ve üç yaprak. Tek
  fark, peşin yazımın `__init__.py` dosyasındaki tek satırdır.
- **MP19** — İki yazımın karşılaştırmasında istenen **tek bir yapraktır** ve sayım her
  ölçümden önce sıfırlanır; iki ölçüm birbirinin sayısını taşımaz.

## Ölçüm

```python
"""Paket yapisi: ayni kisa ad iki yazimda hangi nesneye cozulur."""

import importlib
import sys
import tempfile
from pathlib import Path


def govde(ad, ek=""):
    return f"import kayit\nkayit.GOVDE.append('{ad}')\n{ek}"


KAYNAKLAR = {
    "kayit.py": "GOVDE = []\n",
    "paket/__init__.py": govde("paket"),
    "paket/arac.py": govde("paket.arac", "AD = 'paket.arac'\n"),
    "paket/alt/__init__.py": govde("paket.alt"),
    "paket/alt/arac.py": govde("paket.alt.arac", "AD = 'paket.alt.arac'\n"),
    "paket/alt/kullanan.py": govde("paket.alt.kullanan",
                                   "from . import arac as goreli\n"
                                   "from paket import arac as mutlak\n"),
    "yalniz.py": "from . import arac\n",
    "sade/__init__.py": govde("sade"),
    "pesin/__init__.py": govde("pesin", "from . import x, y, z\n"),
}
for kok_ad in ("sade", "pesin"):
    for yaprak in ("x", "y", "z"):
        KAYNAKLAR[f"{kok_ad}/{yaprak}.py"] = govde(f"{kok_ad}.{yaprak}")

TEPELER = ("kayit", "yalniz", "paket", "sade", "pesin")


def kur(kok):
    for ad, metin in KAYNAKLAR.items():
        yol = kok / ad
        yol.parent.mkdir(parents=True, exist_ok=True)
        yol.write_text(metin, encoding="utf-8")
    sys.path.insert(0, str(kok))
    importlib.invalidate_caches()


def sok(kok):
    sys.path.remove(str(kok))
    for ad in list(sys.modules):
        if ad.split(".")[0] in TEPELER:
            sys.modules.pop(ad)


def olc(kok):
    kur(kok)
    kullanan = importlib.import_module("paket.alt.kullanan")
    kayit = sys.modules["kayit"]
    kosan = list(kayit.GOVDE)
    kayitli = sorted(a for a in sys.modules if a.split(".")[0] == "paket")
    goreli, mutlak = kullanan.goreli, kullanan.mutlak
    oznitelik = (sys.modules["paket"].alt is sys.modules["paket.alt"]
                 and sys.modules["paket.alt"].arac
                 is sys.modules["paket.alt.arac"])
    importlib.import_module("paket.alt.arac")
    ikinci_istek = len(kayit.GOVDE) - len(kosan)

    ns_nokta, ns_from = {}, {}
    exec("import paket.arac", ns_nokta)
    exec("from paket import arac", ns_from)
    bagli_nokta = sorted(a for a in ns_nokta if not a.startswith("__"))
    bagli_from = sorted(a for a in ns_from if not a.startswith("__"))
    ayni_nesne = ns_nokta["paket"].arac is ns_from["arac"]

    try:
        importlib.import_module("yalniz")
        hata = "yok"
    except Exception as e:
        hata = type(e).__name__

    kayit.GOVDE.clear()
    importlib.import_module("sade.x")
    sade = list(kayit.GOVDE)
    kayit.GOVDE.clear()
    importlib.import_module("pesin.x")
    pesin = list(kayit.GOVDE)

    sok(kok)
    return {"kosan": kosan, "kayitli": kayitli, "ikinci": ikinci_istek,
            "ayni": goreli is mutlak,
            "goreli_ad": goreli.AD, "mutlak_ad": mutlak.AD,
            "oznitelik": oznitelik, "bagli_nokta": bagli_nokta,
            "bagli_from": bagli_from, "ayni_nesne": ayni_nesne, "hata": hata,
            "sade": sade, "pesin": pesin}


with tempfile.TemporaryDirectory() as d:
    s = olc(Path(d))

print(f"tek istek {len(s['kosan'])} gövde koşturdu: {' -> '.join(s['kosan'])}")
print(f"önbelleğe yazılan paket modülü {len(s['kayitli'])}: {s['kayitli']}")
print(f"aynı alt modül ikinci kez istendiğinde koşan gövde {s['ikinci']}")
print()
print(f"göreli yazım    -> {s['goreli_ad']}")
print(f"mutlak yazım    -> {s['mutlak_ad']}")
print(f"aynı nesne mi   -> {s['ayni']}")
print()
print(f"noktalı yazımın bağladığı ad {s['bagli_nokta']}, "
      f"from yazımının bağladığı ad {s['bagli_from']}")
print(f"ikisinin ulaştığı modül aynı nesne -> {s['ayni_nesne']}")
print(f"alt paket üst pakette öznitelik olarak bağlı -> {s['oznitelik']}")
print(f"paketsiz modülde göreli içe aktarım -> {s['hata']}")
print()
print(f"{'tek yaprak isteği':<22s} {'koşan gövde':>12s}  koşum sırası")
print(f"{'sade paket':<22s} {len(s['sade']):12d}  {' -> '.join(s['sade'])}")
print(f"{'peşin içe aktaran':<22s} {len(s['pesin']):12d}  "
      f"{' -> '.join(s['pesin'])}")
```

```
tek istek 5 gövde koşturdu: paket -> paket.alt -> paket.alt.kullanan -> paket.alt.arac -> paket.arac
önbelleğe yazılan paket modülü 5: ['paket', 'paket.alt', 'paket.alt.arac', 'paket.alt.kullanan', 'paket.arac']
aynı alt modül ikinci kez istendiğinde koşan gövde 0

göreli yazım    -> paket.alt.arac
mutlak yazım    -> paket.arac
aynı nesne mi   -> False

noktalı yazımın bağladığı ad ['paket'], from yazımının bağladığı ad ['arac']
ikisinin ulaştığı modül aynı nesne -> True
alt paket üst pakette öznitelik olarak bağlı -> True
paketsiz modülde göreli içe aktarım -> ImportError

tek yaprak isteği       koşan gövde  koşum sırası
sade paket                        2  sade -> sade.x
peşin içe aktaran                 4  pesin -> pesin.x -> pesin.y -> pesin.z
```

## Beş Gövde, Beş Nesne

İlk satır tek bir isteğin bedelini sırasıyla veriyor. `paket.alt.kullanan` istendi; koşan
gövde **5** oldu. Sıra kendini açıklıyor: önce `paket`, sonra `paket.alt` — noktalı ad soldan
sağa çözülüyor ve her düzeyin gövdesi kendi sırasında koşuyor. Üçüncü sırada istenen modülün
kendi gövdesi başlıyor, ve o gövde iki istek daha yapıyor: göreli istek `paket.alt.arac`'ı,
mutlak istek `paket.arac`'ı koşturuyor.

Var edilen modül nesnesi **5**, tutulan **5** — hepsi önbellekte kayıtlı kalıyor. Üçüncü
satır bunun sonucunu ödüyor: aynı alt modül ikinci kez istendiğinde koşan gövde **0**. İkinci
istek yeni nesne var etmiyor, hiçbir gövdeyi koşturmuyor, yalnız önbellekteki kaydı veriyor.

Buradan çıkan ölçü şudur: **bir paket isteğinin maliyeti istenen modülde bitmez.** Zincirdeki
her düzey ve o düzeylerin gövdelerinde yapılan her istek aynı faturaya girer. Bir paketin
`__init__.py` dosyasının içinde ne varsa, o pakete ait **herhangi** bir modülü isteyen herkes
onu ödemiş olur.

## Aynı Ad, İki Nesne

Orta bölüm dersin ana ölçüsüdür. `paket/alt/kullanan.py` içinde aynı kısa ad iki kez
yazılıyor; göreli yazım **`paket.alt.arac`**, mutlak yazım **`paket.arac`** veriyor ve
`is` karşılaştırması **False**. İki ad, iki ayrı nesne. Var edilen **2**, paylaşılan **0**.

Ayrım tamamen **başlangıç noktasındadır**. Göreli yazım adı isteği yapan modülün paketinden
başlatır; `kullanan` modülü `paket.alt` içinde durduğu için komşusunu bulur. Mutlak yazım
adı arama yolundan başlatır ve kökteki paketi bulur. Kaynak dosyalarda yazan kısa ad
ikisinde de aynıdır; ayrımı yapan yalnız yazımın kendisidir.

Bunun bir de tersi vardır ve önceki dersin ölçtüğü kuraldan çıkar: önbellek kaydı **ada
göre** tutulur, dosyaya göre değil. Aynı kaynak iki ayrı adla istenirse iki ayrı kayıt açılır
ve iki ayrı modül nesnesi var edilir — önceki derste önbellek kaydı silindiğinde ölçülen
durumun aynısı. O iki nesnenin sözlükleri bağımsız olduğu için içlerinde tanımlanan sınıflar
da ayrı nesnelerdir; birinden üretilmiş bir örnek, öbürünün sınıfına göre sınandığında
beklenen yanıtı vermez. Aynı ağaca hem paket adıyla hem de doğrudan erişilebilmesi bu yüzden
bir kolaylık değil, ikiye bölünmüş bir ad alanıdır.

Bunun okuma tarafında bir sonucu var: bir dosyada yalnız kısa adı görmek **hangi modülün**
kastedildiğini söylemez. Aynı satırın anlamı, dosyanın hangi pakette durduğuna bağlıdır.
Dosya bir başka pakete taşındığında göreli istek sessizce başka bir nesneye çözülür ya da hiç
çözülmez; mutlak istek taşınmadan etkilenmez. İki yazım arasındaki seçim bir üslup tercihi
değil, **adın hangi bağlama bağlandığı** kararıdır.

## Hangi Ad Bağlanır

Son bölüm iki yazımın ad bağlama farkını veriyor. Noktalı yazım, isteği yapan tarafta
yalnız **`paket`** adını bağlıyor — alt modülün adını değil. Alt modüle o addan noktayla
ulaşılır, çünkü zincirin her düzeyi bir üstüne öznitelik olarak bağlanmıştır. `from` yazımı
ise yalnız **`arac`** adını bağlıyor; paketin adı isteği yapan tarafta hiç görünmüyor.

İki yazım farklı adlar bağlasa da aynı nesneye ulaşıyor: `is` karşılaştırması **True**. Var
edilen yeni nesne **0**; ikisi de önbellekteki tek kaydı paylaşıyor. Bir sonraki satır bunun
paketler tarafını gösteriyor — üst paketin sözlüğündeki `alt` adı ile önbellekteki
`paket.alt` kaydı **aynı nesnedir**, ve aynısı bir düzey aşağıda da geçerlidir.

Sonraki satır göreli yazımın sınırıdır. Bir pakete ait olmayan modülde göreli istek
**`ImportError`** ile sonuçlanıyor. Neden açıktır: göreli ad, isteği yapan modülün paketinden
başlar; paketi olmayan bir modül için başlanacak yer yoktur. Bu, bir dosyanın **nasıl
koşturulduğuna** bağlı olarak ortaya çıkabilen bir durumdur ve bu konunun son dersinde
ölçülür.

## Peşin İçe Aktarmanın Bedeli

Son tablo aynı isteği iki paket yazımında karşılaştırıyor ve fark tek bir satırdan doğuyor.
Sade pakette tek bir yaprak istendiğinde koşan gövde **2**: paketin kendisi ve istenen yaprak.
Peşin yazımda aynı istek **4** gövde koşturuyor — paketin gövdesi, ve onun kendi içinden
istediği **üç** yaprağın hepsi. İstenen yaprak zaten o üçün içindedir; sıraya bakıldığında
`pesin.x` paketin gövdesi sırasında koşmuş, dış istek ona sıra geldiğinde önbellekte hazır
bulmuştur.

Sayılar oran olarak okunur: kullanıcı **bir** yaprak istedi, **üç** yaprağın bedelini ödedi.
Yaprak sayısı arttıkça bu oran büyür; on yapraklı bir pakette tek bir yaprak isteği on birin
tamamını koşturur. Var edilen modül nesnesi sade yazımda **2**, peşin yazımda **4**; tutulan
da aynı, çünkü hepsi önbellekte kalır.

Bu bir kusur değil, bir **takas**tır ve iki tarafı da ölçülebilir. Peşin yazım kullanıcıya
kısa bir ad verir ve paketi tek bir yüzey gibi gösterir; bedeli, paketin herhangi bir
parçasını isteyen herkese bütün parçaların gövdesini ödetmektir. Sade yazım bedeli isteyene
bırakır; bedeli, kullanıcının hangi alt modülde ne olduğunu bilmesini gerektirmesidir.
Seçimi belirleyen şey, paketin parçalarının **birlikte mi ayrı mı** kullanıldığıdır.

## Özet

- Paket, `__init__.py` dosyasıyla birlikte bir modül nesnesi veren dizindir; noktalı ad
  soldan sağa çözülür, **her düzey ayrı bir nesnedir** ve her düzey bir üstüne öznitelik
  olarak bağlanır.
- Tek bir alt modül isteği **5** gövde koşturdu ve **5** modül nesnesi önbelleğe yazdı;
  aynı modülün ikinci isteği **0** gövde koşturdu.
- Aynı kısa ad göreli yazımda `paket.alt.arac`, mutlak yazımda `paket.arac` verdi ve `is`
  **False** çıktı; ayrımı yapan tek şey adın **nereden başlatıldığıdır**.
- Noktalı yazım yalnız kök paketin adını, `from` yazımı yalnız alınan adı bağlar; ikisi de
  **0** yeni nesne var eder ve aynı modül nesnesini paylaşır.
- `__init__.py` alt modülleri peşin içe aktardığında tek bir yaprak isteği **2** yerine
  **4** gövde koşturur; kullanıcı bir yaprak ister, üçünün bedelini öder.
- Pakete ait olmayan bir modülde göreli içe aktarım `ImportError` verir, çünkü adın
  başlayacağı bir paket yoktur.

## Sonraki Adım

Buraya kadar ölçülen paketlerin hepsi ölçüm için üretildi: gövdeleri bir satırlık, işleri
kendilerini saydırmaktı. Oysa her koşumda hazır bulunan, hiçbir kurulum gerektirmeyen büyük
bir paket kümesi vardır ve dilin kendisiyle birlikte gelir. Sonraki ders o kümenin kapsamına
bakıyor ve tek bir soruyla ölçüyor: aynı işi standart kitaplıktan bir modülle yazmakla elle
yazmak arasında **kaç nesne** ve **kaç satır** fark var, ve elle yazım hangi durumlarda
sessizce ayrışıyor?
