---
title: 'Modül Sistemi'
source: 'https://academia.sh/tr/kurslar/python-veri-yapilari/modul-sistemi'
course: 'Veri Yapıları ve Fonksiyonel Araçlar'
language: tr
updated: '2026-08-17T18:10:26+00:00'
license: 'CC BY-SA 4.0'
---

# Modül Sistemi

İçe aktarma bir var etme işidir: aynı modül üç kez istendiğinde iki nesne var edilir, gövde önbellek doluyken bir kez koşar; arama yolunun sırası ancak önbellek boşken karar verir.

Buraya kadar her şey **tek bir dosyanın** içindeydi. Kavramalar, üreteçler, sarmalayıcılar
ve dekoratörler aynı ad alanında durdu; bir ad tanımlandığı yerden görünüyordu ve
görünmediğinde nedeni kapsamdı. Kod birden çok dosyaya yayıldığında bu sorunun biçimi
değişir: adlar artık **nereye** yazılır ve bir dosya öbürünün adını **hangi işlemle** alır?

Yanıt bu kursun ölçü ekseniyle verilir. İçe aktarma bir ad kopyalama işlemi değil, bir
**var etme** işidir: bir dosya ilk kez istendiğinde ondan bir **modül (module)** nesnesi var
edilir, gövdesi bir kez koşar ve bütün modül düzeyindeki adlar o nesnenin sözlüğüne yazılır.
İkinci istek yeni bir nesne var etmez. Bu dersin sorusu şudur: aynı modül birden çok kez
istendiğinde **kaç nesne var edilir**, **gövde kaç kez koşar** ve **hangi kayıt** ikinci
koşumu engeller?

## İçe Aktarma Neyi Var Eder

Bir içe aktarma isteği üç iş yapar. Önce adın **modül önbelleğinde (module cache)** kayıtlı
olup olmadığına bakılır; kayıtlıysa oradaki nesne verilir ve iş biter. Kayıtlı değilse
kaynak **arama yolunda (search path)** aranır, bulunan kaynaktan bir modül nesnesi var
edilir, o nesne **önce önbelleğe yazılır**, sonra gövdesi koşturulur. Son adımda istekte
geçen ad, isteği yapan tarafta modül nesnesine bağlanır.

Sıralamanın ayrıntısı önemlidir: nesne önbelleğe **gövde koşmadan önce** yazılır. Bu yüzden
bir modülün gövdesi kendisini dolaylı olarak isteyen başka bir modülü içe aktarsa bile
sonsuz döngü doğmaz — ikinci istek, gövdesi henüz bitmemiş ama nesnesi var edilmiş modülü
önbellekte bulur.

Bunun doğrudan bir sonucu var: içe aktarma **ucuz değildir, bir kez pahalıdır**. Gövdede ne
varsa — sınıf tanımları, modül düzeyindeki hesaplar, tablolar — hepsi ilk istekte bir kez
koşar ve sonuçları modül nesnesinde tutulur. Sonraki istekler yalnızca bir sözlük araması
kadar iş yapar.

## İki Yazım, Aynı Nesne

İçe aktarmanın iki yazımı vardır ve ikisi de **aynı modül nesnesini** var eder; ayrıldıkları
yer, isteği yapan tarafta **hangi adın neye bağlandığıdır**. Birinci yazım modül nesnesinin
kendisini bir ada bağlar; ikinci yazım modülün sözlüğünden **tek bir değeri** okur ve o değeri
yerel bir ada bağlar. İkincisi yeni nesne var etmez — var edilmiş bir nesneye ikinci bir ad
verir.

Ayrımın gözlenebilir sonucu şudur: iki ad **nesneyi** paylaşır, **bağı** paylaşmaz. Modülün
sözlüğündeki ad sonradan başka bir nesneye bağlanırsa, dışarıda alınmış ad eski nesnede
kalır — çünkü o ad modülün sözlüğüne değil, kendi sözlüğüne yazılmıştır. Buna karşılık
paylaşılan nesne yerinde değiştirilirse, iki taraf da aynı değişikliği görür. Ölçümün son
bölümü bu iki durumu ayrı ayrı sınıyor.

## Arama Yolu Bir Listedir

Önbellekte bulunmayan bir ad için sıra arama yoluna gelir. Arama yolu bir dizin adları
listesidir ve **sıralıdır**: ilk eşleşen kaynak kazanır, geri kalanına bakılmaz. İki ayrı
dizinde aynı adı taşıyan iki kaynak varsa, hangisinin içe aktarılacağını dosyaların içeriği
değil listedeki **sıra** belirler.

Sıranın pratik sonucu, arama yolunun **baş tarafındaki** bir dizinde standart kitaplıkla aynı
adı taşıyan bir dosya bulunduğunda ortaya çıkar: istek o dosyayı bulur ve standart kitaplığın
modülü hiç aranmaz. Ortada bir hata iletisi yoktur, çünkü kural doğru işlemiştir — ilk
eşleşen kazanmıştır. Ad çakışmasının belirtisi, beklenen adın modülde bulunamamasıdır; nedeni
ise adın **başka bir kaynaktan** gelmiş olmasıdır.

Bu iki düzenek — önbellek ve arama yolu — birlikte çalışırken hangisinin önce söz sahibi
olduğu ölçülebilir bir sorudur. Arama yolunun sırasını bir modül içe aktarıldıktan sonra
değiştirirsek, sonraki istek yeni sıraya mı uyar yoksa önbellekteki eski nesneyi mi verir?
Ölçüm bunu yanıtlıyor.

## Modül Düzeyindeki Ad Nereye Yazılır

Kapsam kuralları bu kursun konusu değil; dört düzey — yerel, kapsayan, genel, yerleşik —
**Python Temelleri** kursunun kapsam dersinde kuruldu ve burada tekrarlanmaz. Buraya eklenen
tek şey şudur: o dört düzeyden **genel** olanı soyut bir alan değil, somut bir nesnenin
sözlüğüdür. Modül düzeyinde bağlanan her ad, o modül nesnesinin `__dict__` sözlüğüne yazılır;
`vars` yerleşiği aynı sözlüğü verir. Bir modüle dışarıdan öznitelik atamak da aynı sözlüğe
yazmaktır.

Bu, "genel değişken" deyiminin neden yanıltıcı olduğunu açıklar. Genel olan hiçbir şey
yoktur; **modüle ait** olan vardır. İki modülün aynı adı taşıyan iki değişkeni birbirinden
bağımsızdır, çünkü iki ayrı sözlükte dururlar.

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

- **MP1** — Ölçüm depoya dosya bırakmaz. Modül kaynakları geçici bir dizinde üretilir, iş
  bitince dizin silinir; **dizinin yolu basılmaz.**
- **MP2** — Standart kitaplıktan yapılan içe aktarma gerçek bir içe aktarmadır; kâhin `is`
  karşılaştırmasıdır ve **kimlik sayısı basılmaz.**
- **MP3** — Gövdenin kaç kez koştuğu, gövdenin kendisinin ortak bir listeye eklediği kayıtla
  sayılır. Sayan taraf ölçülen modülün kendisidir.
- **MP4** — Var edilen modül nesnesi sayısı, görülen nesneler bir listede toplanıp `is` ile
  birbirinden ayrılarak bulunur.
- **MP5** — Arama yolu ölçümünde iki ayrı dizin **aynı adı** taşıyan iki kaynak içerir;
  ikisi yalnız modül düzeyindeki bir adın değeriyle ayrılır.
- **MP6** — Sıra değiştirildikten sonra önbelleğe iki kez bakılır: bir kez dolu, bir kez
  boşaltılmış.
- **MP7** — Ölçüm bittiğinde eklenen yol girdileri ve önbellek kayıtları geri alınır;
  yorumlayıcının başlangıç durumu ölçüme karışmaz.
- **MP8** — Adın nereye yazıldığı `vars` ile okunur; `vars` ile `__dict__` sonucunun aynı
  nesne olduğu da `is` ile sınanır.
- **MP9** — İki yazımın karşılaştırmasında ikinci yazım ayrı bir ad alanı sözlüğünde
  koşturulur; ölçüm ana koşumun kendi adlarına dokunmaz.
- **MP10** — Paylaşımın sınanması iki adımlıdır: önce nesne yerinde değiştirilir, sonra
  modüldeki ad başka bir nesneye bağlanır. İki adım ayrı ayrı okunur.

## Ölçüm

```python
"""Modul sistemi: ice aktarma kac nesne var eder, govde kac kez calisir."""

import importlib
import sys
import tempfile
from pathlib import Path

KAYIT_KAYNAK = "GOVDE = []\n"
OLCUM_KAYNAK = ("import kayit\n"
                "kayit.GOVDE.append('kosum')\n"
                "ETIKET = 'olcum'\n")
SECIM_KAYNAK = "KAYNAK = '{ad}'\n"
ADLAR = ("kayit", "olcum", "secim")


def farkli_nesne(nesneler):
    """Kimlik basmadan, kac ayri nesne goruldugunu sayar."""
    farkli = []
    for n in nesneler:
        if not any(n is f for f in farkli):
            farkli.append(n)
    return len(farkli)


def onbellegi_bosalt():
    for ad in ADLAR:
        sys.modules.pop(ad, None)


def iki_kez_ice_aktar():
    import json as birinci
    import json as ikinci
    return birinci is ikinci, "json" in sys.modules


def govde_kac_kez(kok):
    (kok / "kayit.py").write_text(KAYIT_KAYNAK, encoding="utf-8")
    (kok / "olcum.py").write_text(OLCUM_KAYNAK, encoding="utf-8")
    sys.path.insert(0, str(kok))
    importlib.invalidate_caches()
    gorulen = [importlib.import_module("olcum")]
    gorulen.append(importlib.import_module("olcum"))
    kayit = sys.modules["kayit"]
    onbellekli = len(kayit.GOVDE)
    sys.modules.pop("olcum")
    gorulen.append(importlib.import_module("olcum"))
    sonuc = (len(gorulen), farkli_nesne(gorulen), onbellekli,
             len(kayit.GOVDE), gorulen[-1].kayit is kayit)
    sys.path.remove(str(kok))
    onbellegi_bosalt()
    return sonuc


def arama_yolu(kok):
    for ad in ("bir", "iki"):
        (kok / ad).mkdir()
        (kok / ad / "secim.py").write_text(SECIM_KAYNAK.format(ad=ad),
                                           encoding="utf-8")
    bir, iki = str(kok / "bir"), str(kok / "iki")
    sys.path[:0] = [bir, iki]
    importlib.invalidate_caches()
    once = importlib.import_module("secim").KAYNAK
    sys.path.remove(bir)
    sys.path.insert(1, bir)
    onbellekle = importlib.import_module("secim").KAYNAK
    sys.modules.pop("secim")
    onbelleksiz = importlib.import_module("secim").KAYNAK
    sys.path.remove(bir)
    sys.path.remove(iki)
    onbellegi_bosalt()
    return once, onbellekle, onbelleksiz


def modul_duzeyindeki_ad(kok):
    (kok / "secim.py").write_text(SECIM_KAYNAK.format(ad="bir"),
                                  encoding="utf-8")
    sys.path.insert(0, str(kok))
    importlib.invalidate_caches()
    m = importlib.import_module("secim")
    ayni_sozluk = vars(m) is m.__dict__
    icinde = "KAYNAK" in vars(m)
    m.SONRADAN = "eklendi"
    disaridan = vars(m)["SONRADAN"] == "eklendi"
    sys.path.remove(str(kok))
    onbellegi_bosalt()
    return ayni_sozluk, icinde, disaridan


def iki_yazim(kok):
    (kok / "secim.py").write_text("KAYNAK = ['bir']\n", encoding="utf-8")
    sys.path.insert(0, str(kok))
    importlib.invalidate_caches()
    m = importlib.import_module("secim")
    ad_alani = {}
    exec("from secim import KAYNAK", ad_alani)
    paylasiyor = ad_alani["KAYNAK"] is m.KAYNAK
    m.KAYNAK.append("degisti")
    degisimi_gordu = "degisti" in ad_alani["KAYNAK"]
    m.KAYNAK = ["yeni"]
    yeniden_baglamayi_gordu = ad_alani["KAYNAK"] is m.KAYNAK
    sys.path.remove(str(kok))
    onbellegi_bosalt()
    return paylasiyor, degisimi_gordu, yeniden_baglamayi_gordu


ayni, kayitli = iki_kez_ice_aktar()
print(f"iki kez içe aktarılan modül aynı nesne -> {ayni}, "
      f"önbellekte kayıtlı -> {kayitli}")

with tempfile.TemporaryDirectory() as d:
    istek, nesne, onbellekli, temizden, paylasilan = govde_kac_kez(Path(d))
print()
print(f"içe aktarma isteği {istek} | var edilen modül nesnesi {nesne} | "
      f"gövde koşumu önbellekliyken {onbellekli}, önbellek silinince {temizden}")
print(f"iki modülün gördüğü kayıt modülü aynı nesne -> {paylasilan}")

with tempfile.TemporaryDirectory() as d:
    once, onbellekle, onbelleksiz = arama_yolu(Path(d))
print()
print(f"arama yolu sırası bir-iki -> {once}")
print(f"sıra iki-bir, önbellek dolu -> {onbellekle}")
print(f"sıra iki-bir, önbellek silinmiş -> {onbelleksiz}")

with tempfile.TemporaryDirectory() as d:
    ayni_sozluk, icinde, disaridan = modul_duzeyindeki_ad(Path(d))
print()
print(f"vars(m) is m.__dict__ -> {ayni_sozluk} | modül düzeyindeki ad "
      f"sözlükte -> {icinde} | dışarıdan yazılan ad aynı sözlükte -> {disaridan}")

with tempfile.TemporaryDirectory() as d:
    paylasiyor, degisimi, yeniden = iki_yazim(Path(d))
print()
print(f"içeri alınan ad modüldekiyle aynı nesne -> {paylasiyor} | "
      f"nesnenin değişimini gördü -> {degisimi} | "
      f"yeniden bağlamayı gördü -> {yeniden}")
```

```
iki kez içe aktarılan modül aynı nesne -> True, önbellekte kayıtlı -> True

içe aktarma isteği 3 | var edilen modül nesnesi 2 | gövde koşumu önbellekliyken 1, önbellek silinince 2
iki modülün gördüğü kayıt modülü aynı nesne -> True

arama yolu sırası bir-iki -> bir
sıra iki-bir, önbellek dolu -> bir
sıra iki-bir, önbellek silinmiş -> iki

vars(m) is m.__dict__ -> True | modül düzeyindeki ad sözlükte -> True | dışarıdan yazılan ad aynı sözlükte -> True

içeri alınan ad modüldekiyle aynı nesne -> True | nesnenin değişimini gördü -> True | yeniden bağlamayı gördü -> False
```

## Üç İstek, İki Nesne, İki Koşum

İlk satır ortak ölçümün beşinci okumasıdır: aynı modül iki kez istendiğinde iki ad **aynı
nesneye** bağlanır ve o nesne önbellekte kayıtlıdır. Var edilen modül nesnesi **1**, tutulan
**1**, iki adın paylaştığı **1**.

İkinci bölüm bunun bedelini gösteriyor. Üç içe aktarma isteği yapıldı; var edilen modül
nesnesi **2** oldu. İlk iki istek arasında önbellek dolu olduğu için gövde koşumu **1**'de
kaldı — ikinci istek yeni nesne var etmedi, gövdeyi yeniden koşturmadı, yalnız önbellekteki
nesneyi verdi. Üçüncü istekten önce kayıt önbellekten silindi; o istek kaynağı yeniden buldu,
**yeni bir modül nesnesi var etti** ve gövdeyi ikinci kez koşturdu. Gövde koşumu **2**'ye
çıktı.

Sayılan üç şey burada birbirinden ayrılıyor. **Var edilen** modül nesnesi 2, **tutulan** —
yani ölçümün sonunda önbellekte kayıtlı olan — 1, ve **paylaşılan** olan `kayit` modülü.
Son satır bunu söylüyor: ölçüm modülünün gövdesinde içe aktarılan `kayit` ile ana koşumun
önbellekten aldığı `kayit` **aynı nesnedir**. Ölçüm modülü iki ayrı kez var edildi ama
ikisinin de gördüğü kayıt tektir, çünkü onun kaydı hiç silinmedi.

Buradan çıkan kural şudur: **modül nesnesinin sayısı dosya sayısına değil, önbellek
kaydının kaç kez düştüğüne bağlıdır.** Aynı dosyadan iki modül nesnesi var edilebilir ve o
iki nesnenin sözlükleri birbirinden bağımsızdır — birinde tanımlanan sınıf, öbüründe
tanımlanan sınıftan ayrı bir nesnedir. İki nesne aynı kaynaktan üretildiği için aynı adları
taşır; taşıdıkları adların bağlandığı nesneler ise ortak değildir. Bir kimlik sınaması bu
durumda beklenmedik bir sonuç verir: aynı dosyadan gelmiş iki sınıf, aynı ada sahip olduğu
hâlde birbirinin yerine geçmez.

## Sıra mı, Önbellek mi

Üçüncü bölüm iki düzeneği karşı karşıya getiriyor. Arama yolunun başında `bir` dizini
varken içe aktarma **bir** veriyor, beklendiği gibi. Sonra sıra değiştirildi: `iki` başa
alındı. Önbellek dolu olduğu için sonuç değişmedi — hâlâ **bir**. Önbellek kaydı silindikten
sonra aynı istek **iki** verdi.

Bu, önbelleğin arama yolundan **önce** geldiğinin doğrudan kanıtıdır. Arama yolu yalnız
önbellekte kayıt yokken karar verir; kayıt varsa yol hiç okunmaz. Yolu çalışma sırasında
değiştirmenin, o ana kadar içe aktarılmış hiçbir modüle etkisi olmaz.

Dördüncü bölüm adın nereye yazıldığını kapatıyor. `vars` ile `__dict__` **aynı sözlüğü**
veriyor, modül düzeyinde bağlanan ad orada duruyor, ve modüle dışarıdan atanan öznitelik de
**aynı sözlüğe** yazılıyor. Modülün ad alanı ile modülün özniteliklerinin ayrı iki şey
olmadığı buradan görünür: dosyanın içinde `KAYNAK = "bir"` yazmakla, dışarıdan
`m.KAYNAK = "bir"` yazmak aynı sözlükte aynı anahtarı bağlar.

## Nesne Paylaşılır, Bağ Paylaşılmaz

Son bölüm iki yazımın farkını üç değerle veriyor. İçeri alınan ad ile modüldeki ad **aynı
nesneye** bağlı: paylaşılan nesne **1**, var edilen yeni nesne **0**. İkinci yazım hiçbir şey
var etmedi, var edilmiş bir nesneye ikinci bir ad verdi.

İkinci değer paylaşımın canlı olduğunu gösteriyor. Modüldeki nesne **yerinde** değiştirilince
içeri alınan ad değişikliği **gördü** — aynı nesneye baktıkları için başka türlüsü olamazdı.
Üçüncü değer sınırı çiziyor: modüldeki ad başka bir nesneye **yeniden bağlanınca** içeri
alınan ad bunu **görmedi**. O ad artık eski nesnede duruyor ve modülün sözlüğüyle bağı yok.

Ayrımı bir cümleye indirgemek gerekirse: **içe aktarma nesneyi paylaşır, adı kopyalar.** Bir
modülün sonradan değişecek bir adını izlemek gerekiyorsa modülün kendisi içeri alınır ve
erişim her seferinde modül üzerinden yapılır; değişmeyecek bir nesne için ikinci yazım
fazladan bir arama kadar iş kazandırır. İki durum arasındaki fark bir üslup tercihi değil,
ölçülen bir davranış farkıdır.

## Özet

- İçe aktarma bir ad kopyalama değil **var etme** işidir: kaynak bir kez okunur, ondan bir
  modül nesnesi var edilir ve gövde bir kez koşar.
- Sıra önbellek, arama yolu, gövde biçimindedir; nesne önbelleğe **gövde koşmadan önce**
  yazılır ve iki kez içe aktarılan modül **aynı nesnedir**.
- Üç istek, önbellek bir kez silindiğinde **2** modül nesnesi var eder ve gövdeyi **2** kez
  koşturur; önbellek bozulmasaydı ikisi de **1** kalırdı.
- Arama yolunun sırası ancak önbellekte kayıt yokken karar verir: sıra değiştirilip önbellek
  dolu bırakıldığında sonuç değişmez, kayıt silinince değişir.
- Modül düzeyindeki her ad, modül nesnesinin `__dict__` sözlüğüne yazılır; `vars` aynı
  sözlüğü verir ve dışarıdan atanan öznitelik de oraya gider.
- Modülden tek bir ad almak **0** yeni nesne var eder ve nesneyi paylaşır; nesnenin yerinde
  değişimi görünür, modüldeki adın yeniden bağlanması görünmez.

## Sonraki Adım

Ölçümde modüller düz durdu: hepsi arama yolundaki bir dizinin doğrudan içindeydi ve adları
tek parçaydı. Kod büyüdüğünde adlar noktayla bölünür ve dizinler iç içe girer. O zaman aynı
kısa ad birden çok yerde bulunabilir — bir üst dizinde bir tane, bir alt dizinde bir tane
daha. Sonraki ders bu durumu ölçüyor: aynı kısa ad, biri komşuluğa biri kökten yazılmış iki
istekle çağrıldığında **hangi nesneye** çözülür ve iç içe dizinlerin kaç gövdesi koşar?
