Bu bilgiler Eric Matthes’in Kapsamlı Python Kursu Programlama Uygulama ve Proje Tabanlı Giriş kitabından derlenmiştir.

Bu Ders Notu Hakkında

Bu çalışma iki temel konuyu ele almaktadır: Fonksiyonlar ve Sınıflar (Nesne Yönelimli Programlama).

Örnekler; bir kütüphane/kitapçı senaryosu (fonksiyonlar bölümü) ile bir ev robotu ve kitap/sesli kitap senaryosu (sınıflar bölümü) etrafında kurgulanmış, tamamen özgün örneklerdir.

Modüle taşıma örnekleri hakkında: “Fonksiyonlarınızı Modüllerde Saklamak” ve “Sınıfları İçeri Aktarmak” bölümlerinde, bir programı ayrı bir .py dosyasına taşıyıp oradan import etmeyi öğreneceksiniz. Bir modülü import edebilmek için o modülün gerçekten ayrı bir .py dosyası olarak diskte var olması gerekir. Bu yüzden ilgili her bölümde önce o dosyanın içeriği gösterilir; ardından bu kodu kendinizin bir kod düzenleyicisinde (RStudio, VS Code, Not Defteri vb.) ilgili dosya adıyla kaydedip, üzerinde çalıştığınız asıl .py dosyanızla aynı klasöre koymanız gerektiği açıkça belirtilir.

FONKSİYONLAR

Fonksiyonlar, belirli bir işi yapan ve isim verilmiş kod bloklarıdır. Bir işlemi tekrar tekrar yazmak yerine, o işlemi bir kez bir fonksiyon içine yazar ve ihtiyaç duyduğumuz her yerde bu fonksiyonu çağırarak kullanırız. Bu yaklaşım kodun okunabilirliğini artırır, hata ayıklamayı kolaylaştırır ve tekrar eden kod bloklarını ortadan kaldırır.

Bir Fonksiyonu Tanımlamak

Bir fonksiyon def anahtar kelimesi ile tanımlanır. Fonksiyon adından sonra parantez içine parametreler yazılır ve satır iki nokta üst üste (:) ile bitirilir. Fonksiyonun gövdesi bir sonraki satırdan itibaren girintili (indented) olarak yazılır. Fonksiyonun ilk satırında yer alan ve üç tırnak içine alınan açıklama metnine docstring denir; bu, fonksiyonun ne işe yaradığını anlatan bir belgedir.

def yeni_uye_karsila():
    """Kütüphaneye yeni gelen bir üyeyi karşılar."""
    print("Kütüphanemize hoş geldiniz!")

yeni_uye_karsila()
## Kütüphanemize hoş geldiniz!

Bir Fonksiyona Bilgi Göndermek

Fonksiyonu daha esnek hale getirmek için parantez içine bir parametre ekleyebiliriz. Böylece fonksiyon her çağrıldığında farklı bir bilgiyle çalışabilir.

def yeni_uye_karsila(isim):
    """Yeni üyeyi ismiyle karşılar."""
    print(f"Kütüphanemize hoş geldin, {isim}!")

yeni_uye_karsila("Ayşe")
## Kütüphanemize hoş geldin, Ayşe!

Argümanlar ve Parametreler

yeni_uye_karsila() fonksiyonunun tanımında yer alan isim bir parametredir (fonksiyonun işini yapabilmesi için ihtiyaç duyduğu bilgi). Fonksiyonu yeni_uye_karsila("Ayşe") şeklinde çağırdığımızda parantez içine yazdığımız "Ayşe" değeri ise bir argümandır (fonksiyon çağrılırken parametreye atanan gerçek değer). Bu iki terim çoğu zaman birbirinin yerine kullanılsa da aralarındaki fark şudur: parametre fonksiyonun beklediği şey, argüman ise çağrı sırasında gönderilen şeydir.

def toplam_fiyat_hesapla(birim_fiyat, adet):   # birim_fiyat, adet -> parametre
    return birim_fiyat * adet

toplam = toplam_fiyat_hesapla(45, 3)   # 45, 3 -> argüman
print(toplam)
## 135

Argümanlar Göndermek

Bir fonksiyon birden fazla parametre kabul edebilir ve bu parametrelere değer göndermenin birkaç farklı yolu vardır: konumsal argümanlar, anahtar kelime argümanları ve listeler/sözlükler. Bu bölümde bu yöntemleri sırasıyla inceleyeceğiz.

Konumsal Argümanlar

Python varsayılan olarak argümanları, fonksiyon tanımındaki parametrelerin sırasına göre eşleştirir. Buna konumsal argüman denir.

def kitap_tanit(yazar, baslik):
    """Bir kitap hakkında bilgi gösterir."""
    print(f"\n{yazar} yazarına ait bir kitabımız var.")
    print(f"Başlığı: {baslik.title()}.")

kitap_tanit("A. Deniz", "sessiz adalar")
## 
## A. Deniz yazarına ait bir kitabımız var.
## Başlığı: Sessiz Adalar.

Çoklu Fonksiyon Çağırma

Aynı fonksiyonu, farklı argüman değerleriyle istediğimiz kadar çağırabiliriz. Bu, fonksiyonların en büyük avantajlarından biridir: kod bir kez yazılır, defalarca kullanılır.

kitap_tanit("A. Deniz", "sessiz adalar")
## 
## A. Deniz yazarına ait bir kitabımız var.
## Başlığı: Sessiz Adalar.
kitap_tanit("M. Yıldız", "kayıp zaman")
## 
## M. Yıldız yazarına ait bir kitabımız var.
## Başlığı: Kayıp Zaman.
kitap_tanit("E. Kaya", "gece yarısı treni")
## 
## E. Kaya yazarına ait bir kitabımız var.
## Başlığı: Gece Yarısı Treni.

Konumsal Argümanlarda Sıralama Önemlidir

Konumsal argümanları yanlış sırada göndermek, mantıksal olarak hatalı ama hata mesajı vermeyen (çalışan) bir sonuç üretebilir. Bu tür hatalar fark edilmesi zor olduğu için dikkatli olunmalıdır. Aşağıdaki çağrıda değerler kasıtlı olarak yer değiştirmiştir; çıktının anlamsal olarak nasıl bozulduğuna dikkat edin:

# Yanlış sıralama: değerler yer değiştirdi
kitap_tanit("sessiz adalar", "A. Deniz")
## 
## sessiz adalar yazarına ait bir kitabımız var.
## Başlığı: A. Deniz.

Anahtar Kelime Argümanlar

Anahtar kelime argümanında, parametre adı ile değeri birlikte gönderilir (parametre=değer). Bu sayede argümanların sırası önemini yitirir ve kodun okunurluğu artar.

kitap_tanit(baslik="sessiz adalar", yazar="A. Deniz")
## 
## A. Deniz yazarına ait bir kitabımız var.
## Başlığı: Sessiz Adalar.

Varsayılan Değerler

Bir parametreye fonksiyon tanımında varsayılan bir değer atanabilir. Çağrı sırasında o parametreye ait argüman gönderilmezse Python varsayılan değeri kullanır; gönderilirse varsayılan değerin üzerine yazılır.

def kitap_tanit(baslik, yazar="Bilinmiyor"):
    print(f"\n\"{baslik.title()}\" adlı kitabımız var.")
    print(f"Yazarı: {yazar}.")

kitap_tanit(baslik="sessiz adalar")                     # varsayılan değer kullanılır
## 
## "Sessiz Adalar" adlı kitabımız var.
## Yazarı: Bilinmiyor.
kitap_tanit(baslik="kayıp zaman", yazar="M. Yıldız")     # varsayılan değer değiştirilir
## 
## "Kayıp Zaman" adlı kitabımız var.
## Yazarı: M. Yıldız.

Önemli Not: Varsayılan değere sahip parametreler, tanım satırında varsayılan değeri olmayan parametrelerden sonra yazılmalıdır; aksi halde Python hata verir.

Eş Değer Fonksiyon Çağrıları

Konumsal, anahtar kelime ve varsayılan değer yaklaşımları bir arada kullanılabilir. Aşağıdaki üç çağrı da birbirine eşdeğerdir ve aynı çıktıyı üretir:

def kitap_tanit(baslik, yazar="Bilinmiyor"):
    print(f"\n\"{baslik.title()}\" - {yazar}")

# 1) Konumsal
kitap_tanit("sessiz adalar")
## 
## "Sessiz Adalar" - Bilinmiyor
# 2) Anahtar kelime
kitap_tanit(baslik="sessiz adalar")
## 
## "Sessiz Adalar" - Bilinmiyor
# 3) Konumsal + anahtar kelime karışık
kitap_tanit("sessiz adalar", yazar="Bilinmiyor")
## 
## "Sessiz Adalar" - Bilinmiyor

Argüman Hatalarından Kaçınmak

Eksik ya da fazla argüman gönderildiğinde Python bir TypeError fırlatır. Bu hata mesajları, hangi argümanın eksik olduğunu genellikle açıkça belirtir; hata izini (traceback) dikkatlice okumak sorunu hızlıca çözmemize yardımcı olur.

def kitap_tanit(yazar, baslik):
    print(f"\n{yazar} yazarına ait \"{baslik}\" adlı kitabımız var.")

kitap_tanit()  # Hiç argüman gönderilmedi
## TypeError: kitap_tanit() missing 2 required positional arguments: 'yazar' and 'baslik'

Döndürülen Değerler

Bir fonksiyon, ekrana bir şey yazdırmak yerine (ya da bunun yanında) bir değer döndürebilir. return ifadesiyle döndürülen değer, fonksiyonu çağıran koda aktarılır ve bir değişkende saklanabilir.

Basit Bir Değer Döndürmek

def yazar_adi_olustur(ad, soyad):
    """Ad ve soyadı birleştirip düzgün biçimli yazar adı döndürür."""
    tam_isim = f"{ad} {soyad}"
    return tam_isim.title()

yazar_adi = yazar_adi_olustur("elif", "kara")
print(yazar_adi)
## Elif Kara

Bir Argümanı İsteğe Bağlı Hâle Getirmek

Bir parametreye boş bir varsayılan değer (örneğin boş dize "") vererek o argümanı isteğe bağlı hale getirebiliriz. Fonksiyon içinde bir if koşuluyla bu değerin gönderilip gönderilmediği kontrol edilir.

def yazar_adi_olustur(ad, soyad, mahlas=""):
    """Ad, soyad ve isteğe bağlı mahlası birleştirir."""
    if mahlas:
        tam_isim = f'{ad} "{mahlas}" {soyad}'
    else:
        tam_isim = f"{ad} {soyad}"
    return tam_isim.title()

print(yazar_adi_olustur("elif", "kara"))
## Elif Kara
print(yazar_adi_olustur("elif", "kara", "e.k."))
## Elif "E.K." Kara

Sözlük Döndürmek

Bir fonksiyon, herhangi bir veri türünü -bir sayı, bir dize, bir liste ya da bir sözlük- döndürebilir. Aşağıdaki örnekte kitap bilgileri bir sözlük olarak döndürülüyor.

def kitap_bilgisi_olustur(baslik, yazar, sayfa_sayisi=None):
    """Bir kitapla ilgili bilgileri içeren bir sözlük döndürür."""
    kitap = {"baslik": baslik, "yazar": yazar}
    if sayfa_sayisi:
        kitap["sayfa_sayisi"] = sayfa_sayisi
    return kitap

yeni_kitap = kitap_bilgisi_olustur("Gece Yarısı Treni", "E. Kaya", sayfa_sayisi=284)
print(yeni_kitap)
## {'baslik': 'Gece Yarısı Treni', 'yazar': 'E. Kaya', 'sayfa_sayisi': 284}

while Döngüsünde Fonksiyon Kullanmak

Fonksiyonlar while döngüleriyle birlikte kullanılabilir; örneğin kullanıcıdan tekrar tekrar giriş almak ve bu girdiyi bir fonksiyonla işlemek için. Bu belge otomatik olarak (knit ile) derlendiğinde gerçek bir klavyeden girdi alınamayacağı için, input() yerine önceden hazırlanmış bir girdi kuyruğu kullanılmıştır; kendi .py dosyanızda bu satırları doğrudan input() ile değiştirebilirsiniz.

def yazar_adi_olustur(ad, soyad):
    return f"{ad} {soyad}".title()

girdi_kuyrugu = ["elif", "kara", "burak", "aydın", "q"]

while True:
    print("\nLütfen yazar adını giriniz ('q' çıkmak için):")
    ad = girdi_kuyrugu.pop(0)     # input("Ad: ") yerine
    print(f"Ad: {ad}")
    if ad == "q":
        break

    soyad = girdi_kuyrugu.pop(0)  # input("Soyad: ") yerine
    print(f"Soyad: {soyad}")
    if soyad == "q":
        break

    yazar = yazar_adi_olustur(ad, soyad)
    print(f"\nKataloğa eklendi: {yazar}")
## 
## Lütfen yazar adını giriniz ('q' çıkmak için):
## Ad: elif
## Soyad: kara
## 
## Kataloğa eklendi: Elif Kara
## 
## Lütfen yazar adını giriniz ('q' çıkmak için):
## Ad: burak
## Soyad: aydın
## 
## Kataloğa eklendi: Burak Aydın
## 
## Lütfen yazar adını giriniz ('q' çıkmak için):
## Ad: q

Liste Göndermek

Bir fonksiyona parametre olarak bir liste gönderebiliriz; bu sayede fonksiyon, listedeki elemanlar üzerinde -örneğin bir for döngüsüyle- işlem yapabilir.

def kitaplari_duyur(kitap_listesi):
    """Listedeki her kitap için bir duyuru mesajı yazdırır."""
    for kitap in kitap_listesi:
        mesaj = f"Yeni geldi: {kitap.title()}!"
        print(mesaj)

yeni_gelenler = ["rüzgarın izinde", "unutulan şehir", "kayıp zaman"]
kitaplari_duyur(yeni_gelenler)
## Yeni geldi: Rüzgarın Izinde!
## Yeni geldi: Unutulan Şehir!
## Yeni geldi: Kayıp Zaman!

Fonksiyon İçerisinde Bir Listeyi Değiştirmek

Bir listeyi bir fonksiyona gönderdiğimizde, fonksiyon o listeyi kalıcı olarak değiştirebilir. Bu, büyük miktarda veriyi verimli bir şekilde işlemek için kullanışlıdır. Aşağıdaki örnekte bekleyenler listesinin fonksiyon çağrısından sonra gerçekten boşaldığına dikkat edin:

def kitaplari_rafla(bekleyen_kitaplar, raflanan_kitaplar):
    """Her kitabı işleyip raflanan kitaplar listesine taşır."""
    while bekleyen_kitaplar:
        mevcut_kitap = bekleyen_kitaplar.pop()
        print(f"{mevcut_kitap} rafa kaldırılıyor...")
        raflanan_kitaplar.append(mevcut_kitap)

def raflanan_kitaplari_goster(raflanan_kitaplar):
    print("\nAşağıdaki kitaplar rafa kaldırıldı:")
    for kitap in raflanan_kitaplar:
        print(f"- {kitap}")

bekleyenler = ["sessiz adalar", "kayıp zaman", "gece yarısı treni"]
raflananlar = []

kitaplari_rafla(bekleyenler, raflananlar)
## gece yarısı treni rafa kaldırılıyor...
## kayıp zaman rafa kaldırılıyor...
## sessiz adalar rafa kaldırılıyor...
raflanan_kitaplari_goster(raflananlar)
## 
## Aşağıdaki kitaplar rafa kaldırıldı:
## - gece yarısı treni
## - kayıp zaman
## - sessiz adalar
print(f"\nOrijinal 'bekleyenler' listesi artık boş: {bekleyenler}")
## 
## Orijinal 'bekleyenler' listesi artık boş: []

Bir Fonksiyonun Bir Listeyi Değiştirmesini Önlemek

Fonksiyonun orijinal listeyi değiştirmesini istemiyorsak, listenin bir kopyasını gönderebiliriz. Bu, liste_adi[:] dilimleme (slice) sözdizimiyle yapılır. Bu kez bekleyenler listesinin çağrıdan sonra da dolu kaldığına dikkat edin:

def kitaplari_rafla(bekleyen_kitaplar, raflanan_kitaplar):
    while bekleyen_kitaplar:
        mevcut_kitap = bekleyen_kitaplar.pop()
        print(f"{mevcut_kitap} rafa kaldırılıyor...")
        raflanan_kitaplar.append(mevcut_kitap)

bekleyenler = ["sessiz adalar", "kayıp zaman", "gece yarısı treni"]
raflananlar = []

# Listenin kopyasını göndererek orijinal listeyi koruyoruz
kitaplari_rafla(bekleyenler[:], raflananlar)
## gece yarısı treni rafa kaldırılıyor...
## kayıp zaman rafa kaldırılıyor...
## sessiz adalar rafa kaldırılıyor...
print(f"\nOrijinal 'bekleyenler' listesi hâlâ dolu: {bekleyenler}")
## 
## Orijinal 'bekleyenler' listesi hâlâ dolu: ['sessiz adalar', 'kayıp zaman', 'gece yarısı treni']
print(f"Raflananlar: {raflananlar}")
## Raflananlar: ['gece yarısı treni', 'kayıp zaman', 'sessiz adalar']

Önemli Not: Kopya göndermek her zaman gerekli olmadığı sürece tercih edilmemelidir; çünkü büyük listelerde kopya oluşturmak zaman ve bellek açısından maliyetlidir. Orijinal listeye ihtiyaç yoksa doğrudan listeyi göndermek daha verimlidir.

Keyfi Sayıda Argüman Göndermek

Bazen bir fonksiyonun kaç argüman alacağını önceden bilemeyiz. Python, parametre önüne bir yıldız (*) koyarak fonksiyona keyfi (esnek) sayıda argüman gönderilmesine izin verir. Bu argümanlar fonksiyon içinde bir demet (tuple) olarak toplanır.

def kitap_sepeti_olustur(*kitaplar):
    """Sepete eklenen kitapları listeler."""
    print("\nSepete şu kitaplar ekleniyor:")
    for kitap in kitaplar:
        print(f"- {kitap}")

kitap_sepeti_olustur("Sessiz Adalar")
## 
## Sepete şu kitaplar ekleniyor:
## - Sessiz Adalar
kitap_sepeti_olustur("Kayıp Zaman", "Gece Yarısı Treni", "Unutulan Şehir")
## 
## Sepete şu kitaplar ekleniyor:
## - Kayıp Zaman
## - Gece Yarısı Treni
## - Unutulan Şehir

Konumsal ve Keyfi Argümanları Karıştırmak

Keyfi sayıda argüman kabul eden parametre, fonksiyon tanımında en sona yazılmalıdır. Python önce diğer konumsal ve anahtar kelime argümanlarını eşleştirir, kalan tüm değerleri yıldızlı parametreye toplar.

def siparis_olustur(paket_turu, *kitaplar):
    """Paket türü ve sipariş edilen kitapları gösterir."""
    print(f"\n{paket_turu} hazırlanıyor:")
    for kitap in kitaplar:
        print(f"- {kitap}")

siparis_olustur("Hediye Paketi", "Sessiz Adalar")
## 
## Hediye Paketi hazırlanıyor:
## - Sessiz Adalar
siparis_olustur("Standart Paket", "Kayıp Zaman", "Gece Yarısı Treni", "Unutulan Şehir")
## 
## Standart Paket hazırlanıyor:
## - Kayıp Zaman
## - Gece Yarısı Treni
## - Unutulan Şehir

Keyfi Anahtar Kelime Argümanları Kullanmak

Bazen kaç tane anahtar kelime argümanının geleceğini de önceden bilemeyiz. İki yıldız (**) kullanılarak tanımlanan parametre, gönderilen tüm anahtar kelime argümanlarını bir sözlük olarak toplar.

def uye_profili_olustur(ad, soyad, **ekstra_bilgi):
    """Bir kütüphane üyesi sözlüğü oluşturur."""
    profil = {"ad": ad, "soyad": soyad}
    for anahtar, deger in ekstra_bilgi.items():
        profil[anahtar] = deger
    return profil

uye = uye_profili_olustur(
    "Deniz", "Aksoy",
    favori_tur="Bilim Kurgu", uye_no=1042
)
print(uye)
## {'ad': 'Deniz', 'soyad': 'Aksoy', 'favori_tur': 'Bilim Kurgu', 'uye_no': 1042}

Fonksiyonlarınızı Modüllerde Saklamak

Fonksiyonları ana programdan ayrı, .py uzantılı bir dosyada (modül) saklamak kodu daha düzenli ve tekrar kullanılabilir hale getirir. Aşağıda, bu bölümde kullanacağımız siparis.py modülünün içeriğini görüyorsunuz (bu blok yalnızca referans amaçlıdır, çalıştırılabilir değildir):

# siparis.py dosyası (içerik referansı)
def siparis_olustur(paket_turu, *kitaplar):
    print(f"{paket_turu} hazırlanıyor:")
    for kitap in kitaplar:
        print(f"- {kitap}")

Bu kodu kendiniz oluşturmalısınız. Yukarıdaki kodu bir kod düzenleyicisinde yeni bir dosyaya yapıştırıp siparis.py adıyla kaydedin ve bu dosyayı, üzerinde çalıştığınız asıl Python dosyanızla (ya da bu ders notunu takip ettiğiniz .py/Jupyter dosyanızla) aynı klasöre koyun. Aşağıdaki import örnekleri, siparis.py dosyasının aynı klasörde, elinizin altında hazır olduğunu varsayar; dosyayı oluşturmadan bu örnekleri kendi ortamınızda çalıştırmaya çalışırsanız ModuleNotFoundError hatası alırsınız.

Bir Modülün Tamamını İçe Aktarmak

import module_adi yazarak, modül içindeki tüm fonksiyonları kullanılabilir hale getiririz. Fonksiyonlara erişmek için module_adi.fonksiyon_adi() sözdizimi kullanılır.

import siparis

siparis.siparis_olustur("Hediye Paketi", "Sessiz Adalar")
## Hediye Paketi hazırlanıyor:
## - Sessiz Adalar
siparis.siparis_olustur("Standart Paket", "Kayıp Zaman", "Gece Yarısı Treni")
## Standart Paket hazırlanıyor:
## - Kayıp Zaman
## - Gece Yarısı Treni

Belirli Fonksiyonları İçeri Aktarmak

Modüldeki fonksiyonlardan yalnızca belirli olanları from module_adi import fonksiyon_adi sözdizimiyle içeri aktarabiliriz. Bu durumda modül öneki olmadan doğrudan fonksiyon adını kullanabiliriz.

from siparis import siparis_olustur

siparis_olustur("Hediye Paketi", "Sessiz Adalar")
## Hediye Paketi hazırlanıyor:
## - Sessiz Adalar

Bir Fonksiyona Takma İsim Vermek için as Kullanmak

Fonksiyon adı çok uzunsa, başka bir isimle çakışıyorsa ya da sadece daha kısa bir isim tercih ediliyorsa, as anahtar kelimesiyle bir takma isim (alias) verilebilir.

from siparis import siparis_olustur as yeni_siparis

yeni_siparis("Hediye Paketi", "Sessiz Adalar")
## Hediye Paketi hazırlanıyor:
## - Sessiz Adalar

Bir Modüle Takma İsim Vermek için as Kullanmak

Aynı şekilde, modülün kendisine de bir takma isim verilebilir. Bu, özellikle uzun modül isimlerini kısaltmak için sık kullanılır (örneğin pandas kütüphanesinin geleneksel olarak pd şeklinde içeri aktarılması gibi).

import siparis as sp

sp.siparis_olustur("Hediye Paketi", "Sessiz Adalar")
## Hediye Paketi hazırlanıyor:
## - Sessiz Adalar

Bir Modüldeki Bütün Fonksiyonları İçe Aktarmak

Yıldız (*) operatörü ile bir modüldeki tüm fonksiyonlar, önek kullanmadan içeri aktarılabilir.

from siparis import *

siparis_olustur("Hediye Paketi", "Sessiz Adalar")
## Hediye Paketi hazırlanıyor:
## - Sessiz Adalar

Uyarı: Bu yöntem genellikle önerilmez. Modülde çok sayıda fonksiyon varsa ya da kendi programınızdaki isimlerle çakışan fonksiyon adları varsa beklenmedik hatalara yol açabilir. Okunabilirlik açısından da import module_adi ya da from module_adi import fonksiyon_adi biçimleri tercih edilmelidir.

Fonksiyonlara Stil Vermek

Python topluluğunun benimsediği stil rehberi PEP 8’e göre fonksiyon yazarken dikkat edilmesi gereken bazı noktalar:

  • Fonksiyon adları küçük harflerle ve kelimeler arasında alt çizgi (_) kullanılarak yazılmalıdır (snake_case): kitap_tanit() gibi.
  • Her fonksiyonun ne yaptığını kısaca açıklayan bir docstring bulunmalıdır.
  • Parametrelere varsayılan değer atanırken eşittir işaretinin (=) etrafında boşluk bırakılmamalıdır: def kitap_tanit(baslik, yazar="Bilinmiyor"):
  • Satırlar 79 karakteri aşıyorsa, argümanlar mantıklı bir şekilde alt satırlara bölünmeli ve hizalanmalıdır.
  • Programda birden fazla fonksiyon varsa, aralarına iki boş satır bırakılarak okunabilirlik artırılmalıdır.
  • Tüm import ifadeleri, dosyanın en başında, docstring’lerden sonra yer almalıdır.
def detayli_kitap_bilgisi_olustur(
        baslik, yazar, sayfa_sayisi, yayin_yili):
    """PEP 8'e uygun çok satırlı parametre örneği."""
    print(baslik, yazar)

detayli_kitap_bilgisi_olustur("Sessiz Adalar", "A. Deniz", 320, 2019)
## Sessiz Adalar A. Deniz

Özet

Bu bölümde şunları öğrendik:

  • Fonksiyon tanımlamanın temel sözdizimi (def, docstring, girinti).
  • Fonksiyonlara bilgi göndermenin farklı yolları: konumsal argümanlar, anahtar kelime argümanları, varsayılan değerler.
  • return ile bir değer (sayı, dize, liste, sözlük) döndürmek.
  • Fonksiyonlara liste göndermek ve listenin fonksiyon içinde kalıcı olarak değişip değişmeyeceğini kontrol etmek.
  • *args ve **kwargs ile keyfi sayıda argüman kabul eden fonksiyonlar yazmak.
  • Fonksiyonları modüllerde saklamak ve farklı import yöntemleriyle içeri aktarmak.
  • PEP 8’e uygun, okunabilir fonksiyon yazma alışkanlıkları.

SINIFLAR

Nesne yönelimli programlama (OOP), yazılım geliştirmenin en etkili yaklaşımlarından biridir. Bir sınıf (class), belirli bir türdeki nesnelerin nasıl bilgi taşıyacağını (nitelikler/attributes) ve nasıl davranacağını (metotlar/methods) tanımlayan bir şablondur. Bir sınıftan üretilen her bir nesneye örnek (instance) denir.

Bir Sınıfı Oluşturmak ve Kullanmak

Bir sınıf, class anahtar kelimesiyle tanımlanır. Python geleneğine göre sınıf isimleri BüyükHarfleBaşlar (CapWords / PascalCase) biçiminde yazılır.

Robot Sınıfını Oluşturmak

class Robot:
    """Basit bir ev robotunu temsil etmek için bir girişim."""

    def __init__(self, isim, seri_no):
        """İsim ve seri numarası niteliklerini başlatır."""
        self.isim = isim
        self.seri_no = seri_no

    def calismaya_basla(self):
        """Robotu çalışmaya başlar şekilde simüle eder."""
        print(f"{self.isim} çalışmaya başladı.")

    def sarj_ol(self):
        """Robotu şarj olur şekilde simüle eder."""
        print(f"{self.isim} şimdi şarj oluyor.")

init() Metodu

__init__() metodu, bir sınıftan yeni bir örnek oluşturulduğunda Python tarafından otomatik olarak çalıştırılan özel bir metottur (yapıcı metot / constructor). Başındaki ve sonundaki çift alt çizgiler, bu ismin Python tarafından özel bir amaç için ayrıldığını gösterir. Metodun ilk parametresi her zaman self olmalıdır; bu parametre, oluşturulacak örneğin kendisine referans verir ve Python tarafından otomatik olarak gönderilir; çağrı sırasında bizim bunu belirtmemize gerek yoktur. self.isim ve self.seri_no gibi self ile başlayan değişkenlere nitelik (attribute) denir ve bu nitelikler sınıftan üretilen her örnek tarafından erişilebilir.

Bir Sınıftan Örnek Oluşturmak

Bir sınıf tanımlandıktan sonra, sınıf adını fonksiyon çağrısı gibi kullanarak yeni bir örnek oluşturabiliriz. Niteliklere nokta gösterimi (dot notation) ile, metotlara ise yine nokta gösterimiyle parantez ekleyerek erişilir.

class Robot:
    def __init__(self, isim, seri_no):
        self.isim = isim
        self.seri_no = seri_no

    def calismaya_basla(self):
        print(f"{self.isim} çalışmaya başladı.")

    def sarj_ol(self):
        print(f"{self.isim} şimdi şarj oluyor.")

ev_robotum = Robot("Arya", "RB-204")

print(f"Robotumun adı {ev_robotum.isim}.")
## Robotumun adı Arya.
print(f"Seri numarası {ev_robotum.seri_no}.")
## Seri numarası RB-204.
ev_robotum.calismaya_basla()
## Arya çalışmaya başladı.
ev_robotum.sarj_ol()
## Arya şimdi şarj oluyor.

Sınıflar ve Örneklerle Çalışmak

Sınıflar genellikle gerçek dünyadaki nesneleri (bir kitap, bir kullanıcı, bir cihaz vb.) modellemek için kullanılır. Bu bölümde bir Kitap sınıfı üzerinden nitelikleri kullanmayı ve değiştirmeyi inceleyeceğiz.

Kitap Sınıfı

class Kitap:
    """Bir kitabı temsil etmek için basit bir girişim."""

    def __init__(self, baslik, yazar, sayfa_sayisi):
        """Kitabı tanımlayan temel nitelikleri başlatır."""
        self.baslik = baslik
        self.yazar = yazar
        self.sayfa_sayisi = sayfa_sayisi

    def tanitici_bilgi_al(self):
        """Düzgün biçimlendirilmiş tanıtıcı bilgi döndürür."""
        tanitici_bilgi = f"{self.baslik} - {self.yazar}"
        return tanitici_bilgi.title()

kitabim = Kitap("sessiz adalar", "a. deniz", 320)
print(kitabim.tanitici_bilgi_al())
## Sessiz Adalar - A. Deniz

Bir Niteliğe Varsayılan Değer Vermek

Bir sınıftan üretilen tüm örnekler, aynı başlangıç değerine sahip bir nitelikle başlayabilir. Bu tür bir nitelik __init__() içinde, parametre olarak alınmadan doğrudan tanımlanır.

class Kitap:
    def __init__(self, baslik, yazar, sayfa_sayisi):
        self.baslik = baslik
        self.yazar = yazar
        self.sayfa_sayisi = sayfa_sayisi
        self.okunan_sayfa = 0   # varsayılan değer

    def tanitici_bilgi_al(self):
        return f"{self.baslik} - {self.yazar}".title()

    def okuma_durumunu_goster(self):
        print(f"Şu ana kadar {self.okunan_sayfa} sayfa okundu.")

kitabim = Kitap("sessiz adalar", "a. deniz", 320)
kitabim.okuma_durumunu_goster()
## Şu ana kadar 0 sayfa okundu.

Nitelik Değerlerini Değiştirmek

Bir örneğin nitelik değeri üç farklı şekilde değiştirilebilir: doğrudan örnek üzerinden, bir metot aracılığıyla ya da yine bir metot aracılığıyla mevcut değeri artırarak.

class Kitap:
    def __init__(self, baslik, yazar, sayfa_sayisi):
        self.baslik = baslik
        self.yazar = yazar
        self.sayfa_sayisi = sayfa_sayisi
        self.okunan_sayfa = 0

    def okuma_durumunu_goster(self):
        print(f"Şu ana kadar {self.okunan_sayfa} sayfa okundu.")

    def sayfa_ayarla(self, sayfa):
        """Okunan sayfa sayısını verilen değere ayarlar (geri saymayı engeller)."""
        if sayfa >= self.okunan_sayfa:
            self.okunan_sayfa = sayfa
        else:
            print("Okunan sayfa sayısı geri alınamaz!")

    def sayfa_ilerlet(self, miktar):
        """Okunan sayfa sayısına belirtilen miktarı ekler."""
        if miktar >= 0:
            self.okunan_sayfa += miktar
        else:
            print("Okunan sayfaya negatif değer eklenemez!")

kitabim = Kitap("kayıp zaman", "m. yıldız", 410)

# 1) Doğrudan değiştirme
kitabim.okunan_sayfa = 15

# 2) Metot aracılığıyla ayarlama
kitabim.sayfa_ayarla(80)

# 3) Metot aracılığıyla artırma
kitabim.sayfa_ilerlet(40)
kitabim.okuma_durumunu_goster()
## Şu ana kadar 120 sayfa okundu.

Kalıtım

Bir sınıf, başka bir sınıfın niteliklerini ve metotlarını devralabilir. Bu işleme kalıtım (inheritance) denir. Yeni sınıfa alt sınıf (child/subclass), devraldığı sınıfa ise üst sınıf (parent/superclass) adı verilir. Alt sınıf, üst sınıfın tüm nitelik ve metotlarını miras alır; buna ek olarak kendi nitelik ve metotlarını da tanımlayabilir.

Alt Sınıfın init() Metodu

Bir alt sınıf oluştururken, Python’un üst sınıfın nitelik ve metotlarını otomatik olarak devralabilmesi için super().__init__() çağrısı kullanılır. super(), üst sınıfa özel bir bağlantı sağlayan Python fonksiyonudur.

class Kitap:
    def __init__(self, baslik, yazar, sayfa_sayisi):
        self.baslik = baslik
        self.yazar = yazar
        self.sayfa_sayisi = sayfa_sayisi

    def tanitici_bilgi_al(self):
        return f"{self.baslik} - {self.yazar}".title()


class SesliKitap(Kitap):
    """Sesli kitaplara özgü nitelikleri temsil eder."""

    def __init__(self, baslik, yazar, sayfa_sayisi):
        """Üst sınıfın niteliklerini başlatır."""
        super().__init__(baslik, yazar, sayfa_sayisi)

kayip_zaman_sesli = SesliKitap("kayıp zaman", "m. yıldız", 410)
print(kayip_zaman_sesli.tanitici_bilgi_al())
## Kayıp Zaman - M. Yıldız

Alt Sınıf için Nitelik ve Metotlar Tanımlamak

Bir alt sınıf, üst sınıfa ait olmayan, kendine özgü nitelik ve metotlarla genişletilebilir. Bu nitelikler yalnızca alt sınıftan üretilen örneklerde bulunur.

class Kitap:
    def __init__(self, baslik, yazar, sayfa_sayisi):
        self.baslik = baslik
        self.yazar = yazar
        self.sayfa_sayisi = sayfa_sayisi

    def tanitici_bilgi_al(self):
        return f"{self.baslik} - {self.yazar}".title()


class SesliKitap(Kitap):
    def __init__(self, baslik, yazar, sayfa_sayisi):
        super().__init__(baslik, yazar, sayfa_sayisi)
        self.sure_dakika = 560   # yalnızca SesliKitap'a özgü

    def dinleme_suresini_goster(self):
        saat = self.sure_dakika // 60
        dakika = self.sure_dakika % 60
        print(f"Bu sesli kitap {saat} saat {dakika} dakika sürüyor.")

kayip_zaman_sesli = SesliKitap("kayıp zaman", "m. yıldız", 410)
kayip_zaman_sesli.dinleme_suresini_goster()
## Bu sesli kitap 9 saat 20 dakika sürüyor.

Üst Sınıftaki Metotları Geçersiz Kılmak

Alt sınıf, üst sınıftan devraldığı bir metodu, kendi ihtiyacına göre yeniden tanımlayarak (override) değiştirebilir. Alt sınıfta üst sınıftaki ile aynı isimde bir metot tanımlandığında, Python üst sınıftaki metodu göz ardı eder ve alt sınıftaki tanımı kullanır.

class Kitap:
    def __init__(self, baslik, yazar, sayfa_sayisi):
        self.baslik = baslik
        self.yazar = yazar
        self.sayfa_sayisi = sayfa_sayisi

    def tanitici_bilgi_al(self):
        return f"{self.baslik} - {self.yazar}".title()

    def tuketim_bicimi(self):
        print("Bu kitap sayfalar hâlinde okunur.")


class SesliKitap(Kitap):
    def __init__(self, baslik, yazar, sayfa_sayisi):
        super().__init__(baslik, yazar, sayfa_sayisi)

    def tuketim_bicimi(self):
        """Sesli kitaplar dinlenerek tüketilir."""
        print("Bu kitap dinlenerek tüketilir.")

kayip_zaman_sesli = SesliKitap("kayıp zaman", "m. yıldız", 410)
kayip_zaman_sesli.tuketim_bicimi()
## Bu kitap dinlenerek tüketilir.

Nitelikler Olarak Örnekler

Bir sınıfın parçalarını -daha karmaşık hale geldikçe- ayrı bir sınıfa taşımak faydalı olabilir. Bu yaklaşımda, bir sınıfın örneği, başka bir sınıfın niteliği olarak kullanılır (buna kompozisyon, composition denir). Bu, “her SesliKitap bir Anlatıcı’ya sahiptir” ilişkisini modellemenin doğal bir yoludur.

class Kitap:
    def __init__(self, baslik, yazar, sayfa_sayisi):
        self.baslik = baslik
        self.yazar = yazar
        self.sayfa_sayisi = sayfa_sayisi

    def tanitici_bilgi_al(self):
        return f"{self.baslik} - {self.yazar}".title()


class Anlatici:
    """Bir sesli kitap anlatıcısını temsil etmek için basit bir sınıf."""

    def __init__(self, isim, deneyim_yili=1):
        self.isim = isim
        self.deneyim_yili = deneyim_yili

    def deneyim_seviyesi_goster(self):
        if self.deneyim_yili >= 10:
            seviye = "Usta"
        elif self.deneyim_yili >= 3:
            seviye = "Deneyimli"
        else:
            seviye = "Yeni"
        print(f"{self.isim}: {seviye} anlatıcı ({self.deneyim_yili} yıl).")


class SesliKitap(Kitap):
    def __init__(self, baslik, yazar, sayfa_sayisi):
        super().__init__(baslik, yazar, sayfa_sayisi)
        self.anlatici = Anlatici("Naz Tekin", deneyim_yili=6)   # Anlatici örneği bir nitelik olarak eklendi

kayip_zaman_sesli = SesliKitap("kayıp zaman", "m. yıldız", 410)
print(kayip_zaman_sesli.tanitici_bilgi_al())
## Kayıp Zaman - M. Yıldız
kayip_zaman_sesli.anlatici.deneyim_seviyesi_goster()
## Naz Tekin: Deneyimli anlatıcı (6 yıl).

Gerçek Dünyaya Ait Nesneleri Modellemek

Sınıflar ve kalıtım hiyerarşisi tasarlanırken kendinize şu soruları sormanız faydalı olur: Modellediğim gerçek nesne hangi bilgileri taşımalı? Bu nesne hangi davranışları (metotları) sergilemeli? Ortak nitelik/metotları paylaşan başka nesne türleri var mı (kalıtım için aday mı)? Kod her zaman gerçek dünyayı birebir yansıtmak zorunda değildir; amaç, probleminizi verimli şekilde çözecek kadar gerçekçi bir soyutlama kurmaktır. Sınıflar başlangıçta basit tutulmalı, ihtiyaç ortaya çıktıkça yeni nitelik ve metotlarla genişletilmelidir.

Sınıfları İçeri Aktarmak

Program büyüdükçe, birden fazla sınıfı ayrı bir dosyada (modül) saklamak ve gerektiğinde ana programa içeri aktarmak, kodu daha düzenli hale getirir. Aşağıda, bu bölümde kullanacağımız kitap.py modülünün içeriğini görüyorsunuz (bu blok yalnızca referans amaçlıdır, çalıştırılabilir değildir):

# kitap.py dosyası (içerik referansı)
class Kitap:
    def __init__(self, baslik, yazar, sayfa_sayisi):
        self.baslik = baslik
        self.yazar = yazar
        self.sayfa_sayisi = sayfa_sayisi

    def tanitici_bilgi_al(self):
        return f"{self.baslik} - {self.yazar}".title()


class Anlatici:
    def __init__(self, isim, deneyim_yili=1):
        self.isim = isim
        self.deneyim_yili = deneyim_yili

    def deneyim_seviyesi_goster(self):
        if self.deneyim_yili >= 10:
            seviye = "Usta"
        elif self.deneyim_yili >= 3:
            seviye = "Deneyimli"
        else:
            seviye = "Yeni"
        print(f"{self.isim}: {seviye} anlatıcı ({self.deneyim_yili} yıl).")


class SesliKitap(Kitap):
    def __init__(self, baslik, yazar, sayfa_sayisi):
        super().__init__(baslik, yazar, sayfa_sayisi)
        self.anlatici = Anlatici("Naz Tekin", deneyim_yili=6)

Bu kodu kendiniz oluşturmalısınız. Yukarıdaki kodu bir kod düzenleyicisinde yeni bir dosyaya yapıştırıp kitap.py adıyla kaydedin ve bu dosyayı, üzerinde çalıştığınız asıl Python dosyanızla aynı klasöre koyun. Aşağıdaki import örnekleri, kitap.py dosyasının aynı klasörde hazır olduğunu varsayar.

Tek Bir Sınıfı İçeri Aktarmak

from kitap import Kitap

kitabim = Kitap("sessiz adalar", "a. deniz", 320)
print(kitabim.tanitici_bilgi_al())
## Sessiz Adalar - A. Deniz

Bir Modülde Birden Çok Sınıf Saklamak

Yukarıdaki kitap.py dosyasında görüldüğü gibi, ilişkili birden fazla sınıf (Kitap, Anlatici, SesliKitap) aynı modül içinde birlikte saklanabilir.

Bir Modülden Birden Çok Sınıfı İçe Aktarmak

Bir modülden birden fazla sınıfı, virgülle ayırarak tek bir from...import ifadesiyle içeri aktarabiliriz.

from kitap import Kitap, SesliKitap

kitabim = Kitap("sessiz adalar", "a. deniz", 320)
print(kitabim.tanitici_bilgi_al())
## Sessiz Adalar - A. Deniz
kayip_zaman_sesli = SesliKitap("kayıp zaman", "m. yıldız", 410)
print(kayip_zaman_sesli.tanitici_bilgi_al())
## Kayıp Zaman - M. Yıldız

Bir Modülün Tamamını İçeri Aktarmak

import module_adi sözdizimiyle, modüldeki tüm sınıflara module_adi.SinifAdi biçiminde erişilebilir.

import kitap

kitabim = kitap.Kitap("sessiz adalar", "a. deniz", 320)
kayip_zaman_sesli = kitap.SesliKitap("kayıp zaman", "m. yıldız", 410)

print(kitabim.tanitici_bilgi_al())
## Sessiz Adalar - A. Deniz
print(kayip_zaman_sesli.tanitici_bilgi_al())
## Kayıp Zaman - M. Yıldız

Bir Modüldeki Sınıfların Tamamını İçe Aktarmak

from kitap import *

kitabim = Kitap("sessiz adalar", "a. deniz", 320)
print(kitabim.tanitici_bilgi_al())
## Sessiz Adalar - A. Deniz

Uyarı: Bu yöntem sınıflar için de önerilmez; hangi sınıfların nereden geldiği belirsizleşir ve isim çakışmaları oluşabilir. import kitap ya da açıkça from kitap import Kitap, SesliKitap biçimleri tercih edilmelidir.

Bir Modülü Bir Başka Modüle Aktarmak

Bazen bir sınıf, başka bir modüldeki sınıfı kullanır; bu durumda o modülün de kendi dosyasının başında içeri aktarılması gerekir. Örneğin SesliKitap sınıfını ayrı bir sesli_kitap.py dosyasına taşıdığımızı düşünelim; bu dosyanın içeriği şöyle olurdu (bu blok da yalnızca referans amaçlıdır):

# sesli_kitap.py dosyası (içerik referansı)
from kitap import Kitap   # başka bir modülden içeri aktarma


class Anlatici:
    def __init__(self, isim, deneyim_yili=1):
        self.isim = isim
        self.deneyim_yili = deneyim_yili


class SesliKitap(Kitap):
    def __init__(self, baslik, yazar, sayfa_sayisi):
        super().__init__(baslik, yazar, sayfa_sayisi)
        self.anlatici = Anlatici("Naz Tekin", deneyim_yili=6)

Bu kodu da kendiniz oluşturmalısınız. Yukarıdaki kodu bir kod düzenleyicisinde yeni bir dosyaya yapıştırıp sesli_kitap.py adıyla kaydedin ve bu dosyayı da, kitap.py ile ve asıl çalıştığınız Python dosyanızla aynı klasöre koyun; sesli_kitap.py içindeki from kitap import Kitap satırının çalışabilmesi için kitap.py dosyasının da aynı klasörde bulunması gerekir.

Ana programda ise her iki modülü de içeri aktarabiliriz:

from kitap import Kitap
from sesli_kitap import SesliKitap

kitabim = Kitap("sessiz adalar", "a. deniz", 320)
kayip_zaman_sesli = SesliKitap("kayıp zaman", "m. yıldız", 410)

print(kitabim.tanitici_bilgi_al())
## Sessiz Adalar - A. Deniz
print(kayip_zaman_sesli.tanitici_bilgi_al())
## Kayıp Zaman - M. Yıldız

Takma İsimler Kullanmak

Fonksiyonlarda olduğu gibi, sınıflara da as anahtar kelimesiyle takma isim verilebilir. Bu, uzun sınıf isimlerini kısaltmak ya da isim çakışmalarını önlemek için kullanılır.

from sesli_kitap import SesliKitap as SK

kayip_zaman_sesli = SK("kayıp zaman", "m. yıldız", 410)
print(kayip_zaman_sesli.tanitici_bilgi_al())
## Kayıp Zaman - M. Yıldız

Kendi İş Akışınızı Bulmak

Kod dosyalarını nasıl organize edeceğiniz konusunda tek bir doğru yol yoktur; önemli olan, projeniz büyüdükçe kodun anlaşılır ve yönetilebilir kalmasını sağlamaktır. Genel bir öneri olarak: önce çalışan basit bir sürümle başlayın, gerektikçe sınıfları ayrı modüllere taşıyın ve kodu düzenli aralıklarla test edin. Zamanla, hangi sınıfların birlikte hangilerinin ayrı dosyalarda durması gerektiğine dair kendi sezginizi geliştireceksiniz.

Python Standart Kütüphanesi

Python; kendi kurduğunuz modüllerin yanı sıra, kurulumla birlikte gelen standart kütüphane (standard library) adında zengin bir modül koleksiyonuyla birlikte gelir. Bu modüller ek bir kurulum gerektirmeden import edilebilir. Örneğin random modülü rastgele değer üretmek, collections modülü ise ek veri yapıları sunmak için kullanılır. (Önerilen kitap her knit işleminde değişebilir, çünkü gerçekten rastgele seçilir.)

from random import choice

kitap_onerileri = ["Sessiz Adalar", "Kayıp Zaman", "Gece Yarısı Treni", "Unutulan Şehir"]

# Listeden rastgele bir kitap önerisi seç
onerilen_kitap = choice(kitap_onerileri)
print(f"Bugünün önerisi: {onerilen_kitap}")
## Bugünün önerisi: Gece Yarısı Treni
from collections import OrderedDict

kutuphane_kurallari = OrderedDict()
kutuphane_kurallari["İade süresi"] = "14 gün"
kutuphane_kurallari["Üyelik ücreti"] = "Ücretsiz"
kutuphane_kurallari["Günlük gecikme cezası"] = "1 TL"
for kural, deger in kutuphane_kurallari.items():
    print(f"{kural}: {deger}")
## İade süresi: 14 gün
## Üyelik ücreti: Ücretsiz
## Günlük gecikme cezası: 1 TL

Sınıflara Stil Vermek

Sınıflar için de PEP 8 stil rehberine uymak önerilir:

  • Sınıf isimleri CapWords (her kelimenin ilk harfi büyük, alt çizgi yok) biçiminde yazılmalıdır: SesliKitap, Anlatici gibi. Örnek ve fonksiyon isimleri ise küçük harf ve alt çizgi (snake_case) ile yazılır.
  • Her sınıfın hemen altında, sınıfın ne işe yaradığını açıklayan bir docstring bulunmalıdır. Her metodun da kendi docstring’i olmalıdır.
  • Sınıf içindeki her boş satır, ilişkili kod bloklarını (örneğin metotlar arasını) ayırmak için kullanılabilir; sınıf tanımından sonra ve metotlar arasında bir boş satır bırakmak yeterlidir.
  • Hem kendi modülünüzü içeri aktarma ifadeleri hem de standart kütüphaneden yapılan içe aktarmalar dosyanın başında, mümkünse önce standart kütüphane modülleri, sonra kendi modülleriniz sırasıyla yer almalıdır.
class Kitap:
    def __init__(self, baslik, yazar, sayfa_sayisi):
        self.baslik = baslik
        self.yazar = yazar
        self.sayfa_sayisi = sayfa_sayisi


class Anlatici:
    def __init__(self, isim, deneyim_yili=1):
        self.isim = isim
        self.deneyim_yili = deneyim_yili


class SesliKitap(Kitap):
    """Sesli kitaplara özgü nitelikleri temsil eder."""

    def __init__(self, baslik, yazar, sayfa_sayisi):
        """Üst sınıfın niteliklerini başlatıp anlatıcıyı ekler."""
        super().__init__(baslik, yazar, sayfa_sayisi)
        self.anlatici = Anlatici("Naz Tekin", deneyim_yili=6)

    def anlatici_bilgisi_goster(self):
        """Anlatıcının temel bilgilerini yazdırır."""
        print(f"Anlatıcı: {self.anlatici.isim} ({self.anlatici.deneyim_yili} yıl deneyim)")

kayip_zaman_sesli = SesliKitap("kayıp zaman", "m. yıldız", 410)
kayip_zaman_sesli.anlatici_bilgisi_goster()
## Anlatıcı: Naz Tekin (6 yıl deneyim)

Özet

Bu bölümde şunları öğrendik:

  • Sınıf oluşturmanın temel mantığı: __init__() metodu, self parametresi, nitelikler ve metotlar.
  • Bir sınıftan örnek oluşturmak ve niteliklere/metotlara nokta gösterimiyle erişmek.
  • Nitelik değerlerine varsayılan değer atamak ve bu değerleri farklı yollarla değiştirmek.
  • Kalıtım kavramı: super().__init__(), alt sınıfa özgü nitelik/metot ekleme, üst sınıf metotlarını geçersiz kılma.
  • Kompozisyon: bir sınıfın örneğini başka bir sınıfın niteliği olarak kullanmak.
  • Sınıfları modüllerde saklamak ve farklı import yöntemleriyle içeri aktarmak. Bunu yaparken, importun çalışabilmesi için ilgili .py dosyasının gerçekten diskte -üzerinde çalıştığınız dosyayla aynı klasörde- bulunması gerektiğini gördük.
  • Python standart kütüphanesinin varlığı ve random, collections gibi modüllerden örnekler.
  • Sınıflar için PEP 8 stil kuralları.

Kaynakça

Matthes, E. Python Crash Course: A Hands-On, Project-Based Introduction to Programming (Kapsamlı Python Kursu: Programlama Uygulama ve Proje Tabanlı Giriş). No Starch Press.