Logo
Ana Sayfa
ÖZEL KODLAMA DERSLERİ
Yazılım Özel Ders
Tüm birebir programlara genel bakış
Python Yazılım Kursu
Sıfırdan ileri seviyeye birebir Python
Java Yazılım Kursu
OOP odaklı birebir Java eğitimi
AP Computer Science Principles
AP CSP sınav hazırlığı
GRUP DERSLERİ
Python & Django Masterclass
SINIRLI KONTENJAN
Java & Spring Boot Masterclass
SINIRLI KONTENJAN
C# .NET Masterclass
SINIRLI KONTENJAN
VİDEO DERSLER
Sıfırdan Temel Python Kursu
Kendi Hızında Öğren
ÜCRETSİZ
Seviye Testi
Ücretsiz — Python, Java, algoritma seviye testleri
Kariyerini Keşfet
Sertifika Doğrula
Belge numarası ve soyad ile doğrulama

Python'da Class, Nesne, Self ve __init__ Mantığı Nedir?

Yazar: Berk Keskin 28.08.2026 ~13 dk okuma 4 Okunma
python-class-nesne-self-init-mantigi

Python'da class kavramı, birbiriyle ilişkili veriyi ve bu veri üzerinde çalışan davranışı tek bir kalıp altında toplamanın yoludur; bu kalıptan üretilen her somut kopya bir nesne (object) olarak adlandırılır. self parametresi, bir metodun hangi nesne üzerinde çalıştığını Python'a söyleyen referanstır; __init__ metodu ise bir nesne oluşturulduğu anda otomatik çalışan ve o nesnenin ilk özelliklerini ayarlayan başlatıcı fonksiyondur. Fonksiyon ve döngülerle küçük programlar yazabilen ama verinin çoğaldığı anda kodun dağılmaya başladığını fark eden biri için bu dört kavram, nesne yönelimli programlamaya (OOP) sağlam bir giriş kapısı olur. Aşağıdaki bölümlerde bu mantığın neden gerekli olduğunu, adım adım nasıl kurulduğunu somut örneklerle göreceğiz.

Fonksiyonlar Neden Bir Yerden Sonra Yetersiz Kalır?

Bir sınıftaki öğrencilerin adını ve notunu tutmak istediğinizi düşünün. İlk aklınıza gelen çözüm genellikle basit değişkenlerdir: ogrenci1_ad, ogrenci1_not, ogrenci2_ad, ogrenci2_not gibi. İki öğrenci için bu tolere edilebilir görünür, ama otuz öğrenciyle çalışmaya başladığınızda bu yaklaşım anında çöker. Doğal çözüm olarak listeye veya sözlüğe geçersiniz: isimler = ["Ayşe", "Mert"], notlar = [85, 60] şeklinde iki paralel liste tutarsınız.

Bu noktada işler daha karmaşık hale gelmeye başlar. Ortalama hesaplayan bir fonksiyon yazarsınız, notu güncelleyen başka bir fonksiyon yazarsınız, geçti mi kaldı mı kontrol eden üçüncü bir fonksiyon eklersiniz. Her fonksiyon parametre olarak hangi listenin hangi indeksiyle ilgilendiğini bilmek zorundadır. Bir öğrenciye telefon numarası, devam durumu veya ders programı gibi yeni bir bilgi eklemeniz gerektiğinde, üçüncü bir paralel liste daha açarsınız ve tüm fonksiyonların parametre listesini yeniden düzenlemeniz gerekir.

Buradaki gerçek sorun sadece kod uzunluğu değildir; veri ile o veriyi işleyen davranışın birbirinden tamamen kopmuş olmasıdır. notlar[3] hangi öğrenciye ait, hesapla_ortalama() fonksiyonu hangi listeyle çalışıyor, bunu takip etmek proje büyüdükçe zihinsel bir yüke dönüşür. İsimleri, notları ve bu verilerle ilgili işlemleri ayrı ayrı değil, tek bir bütün halinde bir arada tutmanız gerektiğini fark ettiğiniz an, aslında class kavramına doğru ilk adımı atmış olursunuz. Python'daki sınıf yapısı, tam olarak bu dağınıklığı ortadan kaldırmak için tasarlanmıştır: her öğrenciyi kendi verisini ve kendi davranışını taşıyan bağımsız bir birim haline getirir.

Class, Nesne, Attribute ve Metot Tam Olarak Nedir?

Bir class'ı bir mimari plan gibi düşünebilirsiniz: bir ev planı, evin kaç odası olacağını, kapının nerede duracağını tanımlar ama kendisi oturulabilir bir ev değildir. O plandan inşa edilen her gerçek ev ise bir nesnedir (object) — aynı plana göre yapılmış olsalar da her evin kendi rengi, kendi eşyaları, kendi sakinleri vardır. Python'da da class Ogrenci: gibi bir tanım yalnızca bir şablondur; ayse = Ogrenci(...) yazdığınız an ortaya somut bir nesne çıkar.

Bu benzetmedeki "evin özellikleri" kısmına Python'da attribute denir: bir nesneye ait veridir — öğrencinin adı, notu, numarası gibi. "Evde yapılabilecek işler" kısmına ise metot denir: nesnenin yapabildiği davranıştır — ortalamasını hesaplama, notunu güncelleme gibi bir fonksiyon, ama artık bir nesneye bağlı çalışan bir fonksiyon. Aynı class'tan istediğiniz kadar nesne üretebilirsiniz ve her biri kendi attribute değerlerini bağımsız olarak taşır; ayse.not_ ile mert.not_ aynı isimli attribute olsa da tamamen ayrı hafıza alanlarında, ayrı değerlerle yaşar.

Bu ayrım netleştiği anda önceki bölümdeki dağınıklık kendiliğinden çözülür: paralel listeler ve indeks takibi yerine, her öğrenci kendi verisini ve kendi işlemlerini taşıyan bir nesne olur. Bu mantığı gerçek kod üzerinde adım adım, alıştırmalarla ve geri bildirimle pekiştirmek isteyenler için birebir Python dersleri kapsamında class ve nesne yapıları baştan sona uygulamalı olarak işlenir. Bir sonraki bölümde bu nesnelerin ilk attribute değerlerinin nasıl atandığını, yani __init__ metodunun rolünü ele alacağız.

__init__ Metodu: Nesnenin Doğuş Anı

__init__ Metodu: Nesnenin Doğuş Anı

__init__, adındaki çift alt çizgiden de anlaşılacağı gibi Python'un kendi belirlediği özel bir metottur ve bir kurucu (constructor) görevi görür. Siz bu metodu doğrudan çağırmazsınız; bir class'tan yeni bir nesne oluşturduğunuz anda, Python arka planda __init__ metodunu otomatik olarak çalıştırır. Yani Ogrenci("Ayşe", 85) yazdığınızda, parantez içindeki değerler doğrudan __init__'e gönderilir ve nesne "doğar doğmaz" bu değerlerle donatılır.

__init__'in içinde tipik olarak self.ad = ad gibi satırlar bulunur. Buradaki mantık basittir: sağdaki ad, metoda dışarıdan gelen parametredir; soldaki self.ad ise bu değerin, o anda oluşturulmakta olan nesnenin kalıcı bir attribute'u olarak saklanmasıdır. Bu atama olmadan, parametre olarak gelen değer metot bittiği anda kaybolur; self. ile yapılan atama sayesinde değer nesneye "yapışır" ve nesne yaşadığı sürece erişilebilir kalır.

__init__ olmasaydı ne olurdu diye düşünmek, bu metodun neden var olduğunu daha iyi gösterir. Her yeni öğrenci nesnesi oluşturduğunuzda, o nesnenin adını, notunu ve diğer bilgilerini elle, ayrı ayrı satırlarla atamanız gerekirdi — tıpkı önceki bölümdeki paralel listeler sorununun küçük bir versiyonu gibi. Otuz öğrenci için otuz kez tekrarlanan atama satırları, hem yazım hatasına açık hem de bakımı zor bir yapı ortaya çıkarır. __init__, bu tekrarı tek bir tanım altında toplayarak her nesnenin doğuşunda aynı kuralın otomatik olarak uygulanmasını sağlar; siz sadece değerleri parantez içine yazarsınız, gerisini Python halleder.

Bu noktada akılda tutulması gereken şey, __init__'in bir "başlangıç değerleri belirleme" sözleşmesi olduğudur: nesne oluşturulurken hangi bilgilerin zorunlu olacağını, bu bilgilerin hangi attribute isimleriyle saklanacağını tanımlar. Bir sonraki bölümde, bu atamaların içinde sürekli karşımıza çıkan self parametresinin gerçekte neyi temsil ettiğini ve bu konuda en sık yapılan hataları ayrıntılı olarak inceleyeceğiz.

self Parametresi Gerçekte Nedir ve Sık Yapılan Hatalar

self, Python'ın "bu metodu şu anda hangi nesne için çalıştırıyorum" sorusuna verdiği cevaptır. Bir metodu bir nesne üzerinden çağırdığınızda, Python o nesnenin kendisini otomatik olarak metoda ilk parametre olarak gönderir; siz bunu elle yazmazsınız, sadece metot tanımında yer ayırırsınız. Yani self, gizemli bir anahtar kelime değil, sadece "işlem yapılan nesnenin kendisini tutan" sıradan bir parametredir; adını isterseniz değiştirebilirsiniz ama bu okunabilirliği bozacağı için kimse yapmaz.

self.ad gibi ifadeler tam da bu yüzden gereklidir: siz self.ad = ad yazdığınızda, "bu değeri şu anda elimdeki nesnenin üzerine kalıcı olarak yaz" demiş olursunuz. self olmadan sadece ad yazsanız, bu değer metot bittiği anda uçar; hiçbir nesneye bağlı kalmaz. self, değeri nesnenin hafızasına iğnelemenin tek yoludur.

Yeni başlayanların self ile ilgili düştüğü hatalar oldukça benzer ve tekrar eder. Aşağıdaki tablo bu hataları, neden oluştuğunu ve doğru kullanımını yan yana gösteriyor:

Hata Neden Oluşur Doğru Kullanım
self parametresini unutmak Metot tanımı def bilgi(): şeklinde yazılır, Python otomatik gönderdiği nesneyi karşılayacak parametre bulamaz def bilgi(self): şeklinde her metoda self'i ilk parametre olarak eklemek
self'i metot dışında kullanmaya çalışmak self, sadece bir metot çağrıldığında o an işlenen nesneyi temsil eder; sınıfın dışında böyle bir bağlam yoktur self yalnızca sınıf içindeki metotların içinde kullanılır, sınıf dışında nesne adı üzerinden erişim yapılır
self.ad ile yerel değişken ad'ı karıştırmak __init__(self, ad) içinde ad parametresi geçicidir, self.ad ise nesneye kalıcı bağlanan attribute'tur; ikisi aynı isme sahip olsa da farklı şeylerdir Parametreden gelen değeri self.ad = ad ile nesneye açıkça atamak, sadece ad yazıp geçmemek

Bu ayrımı net görmek için soyut anlatım yerine küçük alıştırmalarla kendinizi sınamak işe yarar. Konuyu okuduktan sonra ne kadar oturduğunu ölçmek isteyenler ücretsiz Python bilgi testi ile self, class ve __init__ ile ilgili sorularda kendini deneyebilir; yanlış yaptığınız noktalar tam olarak yukarıdaki tablodaki hata kalıplarından çıkar.

Adım Adım Bir Sınıf Yazmak

Adım Adım Bir Sınıf Yazmak

Class, __init__ ve self kavramlarını tek tek anladıktan sonra geriye bunları bir sıraya dizmek kalıyor. Sınıf yazmak, aslında her zaman aynı mantığı takip eden, ezberlenebilir bir akıştır. Bu akışı bir kez içselleştirdiğinizde, karşınıza çıkan her yeni sınıf ihtiyacında aynı adımları otomatik olarak uygularsınız.

Sınıf Yazma Adımları

  1. class anahtar kelimesiyle sınıfa bir isim belirleyin; isim genellikle büyük harfle başlar (örneğin Ogrenci, Araba, Kitap).
  2. Sınıfın içine __init__ metodunu tanımlayın; bu metot, sınıftan her yeni nesne oluşturulduğunda otomatik çalışır.
  3. __init__ metoduna, nesnenin sahip olması gereken bilgiler için parametreler ekleyin ve bunları self ile nesnenin attribute'larına atayın.
  4. Nesnenin yapabileceği davranışlar için ayrı metotlar yazın; her metot da ilk parametre olarak self alır.
  5. Sınıftan bir nesne oluşturun; bu işlem SinifAdi(parametreler) şeklinde yapılır ve Python arka planda __init__ metodunu çalıştırır.
  6. Oluşturduğunuz nesne üzerinden nokta (.) operatörüyle attribute'lara ulaşın veya metotları çağırın.

Bu altı adım, karmaşık görünen "nesne yönelimli programlama" fikrini aslında oldukça mekanik bir sıraya indirir. İlk sınıflarınızı yazarken bu listeyi yanınızda bir kontrol listesi gibi tutabilirsiniz; her yeni sınıf denemesinde hangi adımda olduğunuzu sorgulamak, kod yazarken kaybolmanızı önler.

Dikkat edilmesi gereken nokta, bu adımların sırasının rastgele olmamasıdır. Önce isim, sonra doğuş anı (__init__), sonra bilgiler (attribute), sonra davranışlar (metot), sonra somut örnek (nesne) ve en son o örneği kullanma. Fonksiyon yazarken alıştığınız "girdi al, işle, çıktı ver" mantığından farklı olarak burada önce bir şablon kuruyor, sonra o şablondan istediğiniz kadar somut örnek üretiyorsunuz. Bir sonraki bölümde bu altı adımı gerçek bir Ogrenci sınıfı üzerinden uygulamalı olarak göreceksiniz; her adımın kodun neresine karşılık geldiğini birebir takip edebileceksiniz.

Uygulamalı Örnek: Bir 'Ogrenci' Sınıfı

Teoriyi somutlaştırmanın en iyi yolu, önceki bölümdeki altı adımı gerçek bir örnekte adım adım uygulamaktır. Aşağıdaki Ogrenci sınıfı, __init__ metoduyla ad ve not attribute'larını nasıl atadığını, bir metotla nesnenin davranışını nasıl tanımladığını ve iki farklı nesnenin bu şablondan nasıl bağımsız üretildiğini gösterir:

class Ogrenci:
    def __init__(self, ad, not_ortalamasi):
        self.ad = ad
        self.not_ortalamasi = not_ortalamasi

    def durumu_degerlendir(self):
        if self.not_ortalamasi >= 50:
            print(f"{self.ad} dersi gecti.")
        else:
            print(f"{self.ad} dersi gecemedi.")

ogrenci1 = Ogrenci("Ayse", 78)
ogrenci2 = Ogrenci("Mehmet", 42)

ogrenci1.durumu_degerlendir()
ogrenci2.durumu_degerlendir()

Bu kodu çalıştırdığınızda ekranda iki farklı sonuç görürsünüz: biri geçti, biri geçemedi. Burada dikkat çeken nokta, durumu_degerlendir metodunun tek bir kod bloğu olmasına rağmen her nesne için farklı sonuç üretmesidir. Bunun sebebi self.ad ve self.not_ortalamasi ifadelerinin her çağrıda o anki nesnenin kendi değerlerine bakmasıdır; ogrenci1 için self, ogrenci1'in kendisini işaret ederken, ogrenci2 için self, ogrenci2'yi işaret eder. Aynı şablon, farklı veriyle beslendiğinde farklı sonuç üretir; nesne yönelimli programlamanın pratikte gösterdiği tam olarak budur.

Bu örnek kağıt üzerinde basit görünse de, gerçek bir uygulamada onlarca attribute ve metotla büyüdüğünde kafa karışıklığı yaratabilir. Kendi projelerinizde class, __init__ ve self kullanırken tıkandığınız noktaları birebir geri bildirimle çözmek isterseniz, Python özel ders seçeneğiyle kendi kod örnekleriniz üzerinden çalışabilir, hata yaptığınız yeri anında görebilirsiniz. Bir sonraki bölümde ise bu Ogrenci örneğinden yola çıkarak, ne zaman sınıf yazmanın gerçekten gerekli olduğuna, ne zaman sade bir fonksiyonun yeterli kalacağına bakacağız.

Ne Zaman Fonksiyon, Ne Zaman Sınıf Kullanılmalı?

Bu soru, class kavramını öğrenen her öğrencinin kafasında bir süre dönüp durur. Cevap aslında karmaşık değil: elindeki problemi birkaç somut soruyla test ettiğinde karar kendiliğinden ortaya çıkar. Sınıf kullanmak için "OOP öğrendim, her yerde kullanmalıyım" demek yanlış bir refleks olur; doğru soru şudur: veri ile o veriyi işleyen davranış birlikte mi hareket ediyor?

Kararı somutlaştırmak için şu kriterlere bakabilirsin:

  • Veri (isim, not, bakiye gibi bilgiler) ile bu veriyi işleyen davranış (hesaplama, güncelleme, kontrol) sürekli birlikte mi taşınıyor?
  • Aynı yapıdan birden fazla örnek üretmen gerekiyor mu? Yani "öğrenci1", "öğrenci2", "öğrenci3" gibi benzer ama birbirinden bağımsız nesnelere ihtiyaç var mı?
  • Zamanla değişen ve saklanması gereken bir durum (state) mevcut mu? Örneğin bir öğrencinin notu güncellendiğinde bu bilginin bir yerde tutulması gerekiyor mu?
  • Fonksiyonlarına her seferinde aynı parametre grubunu (isim, yaş, not gibi) tekrar tekrar geçirmek zorunda kalıyor musun?

Bu sorulardan birkaçına "evet" cevabı veriyorsan, class kullanmak işini kolaylaştırır. Çünkü sınıf, veriyi ve davranışı tek bir çatı altında toplayarak parametre tekrarını ortadan kaldırır ve her nesnenin kendi durumunu kendi içinde saklamasını sağlar.

Ama madalyonun diğer yüzü de önemli. Basit, tek seferlik bir işlem yapıyorsan — iki sayıyı toplamak, bir listeyi sıralamak, bir metni büyük harfe çevirmek gibi — fonksiyon hâlâ en doğru ve en sade çözümdür. Her küçük işi sınıfa dönüştürmek, kodunu gereksiz yere şişirir ve okunabilirliği azaltır. Bir fonksiyonun yeterli olduğu yerde class yazmak, aslında bir problemi çözmek değil, yeni bir problem yaratmaktır. Deneyimli geliştiricilerin çoğu, önce fonksiyonla başlar; ihtiyaç gerçekten class'ı işaret ettiğinde koda yeniden şekil verir. Bu, doğru sırayla öğrenmenin ve doğru sırayla kod yazmanın en pratik göstergesidir.

Bu Yazının Kapsamı Dışında Kalanlar

Bu yazı bilinçli olarak sınırlı bir alana odaklandı: class, nesne, self ve __init__ mantığını sağlam bir şekilde anlamak. Nesne yönelimli programlamanın (OOP) dünyası bundan çok daha geniştir ve bu yazıda kalıtım, polimorfizm, encapsulation ve çoklu miras konularına hiç girilmedi. Bunlar bilinçli bir tercih; çünkü bu kavramlar, ancak class ve self mantığı iyice içselleştirildikten sonra anlam kazanır.

Kalıtım, bir sınıfın başka bir sınıftan özellik ve davranış devralmasını sağlar; polimorfizm, aynı metodun farklı sınıflarda farklı şekilde çalışabilmesi anlamına gelir; encapsulation ise verinin dışarıdan kontrolsüz erişime karşı korunmasıyla ilgilidir. Çoklu miras ise bir sınıfın birden fazla sınıftan aynı anda özellik alabilmesi durumudur. Bunların hepsi gerçek ve önemli konulardır, ama temel olmadan öğrenilmeye çalışıldığında kafa karışıklığı yaratma olasılığı çok yüksektir.

Bu yüzden önerimiz net: önce class, nesne, self ve __init__ mantığını elinle kod yazarak, hatalarını görerek, düzelterek pekiştir. Bir sınıftan nesne türetmek, bu nesnenin kendi verisini nasıl taşıdığını gözlemlemek ve self ile bu verilere nasıl ulaşıldığını anlamak sana OOP'nin gerçek zeminini verir. Bu zemin oturduktan sonra kalıtım ve diğer ileri konulara geçmek çok daha doğal ve çok daha hızlı olur; aksi hâlde her yeni kavram önceki eksik anlaşılmış kavramın üzerine bina edilir ve sonunda hiçbiri tam yerine oturmaz.

Python'da öğrenilecek çok daha fazla konu var: veri yapıları, hata yönetimi, dosya işlemleri, modüller ve elbette OOP'nin ileri seviyeleri. Bu konuları adım adım, doğru sırayla işlemek isteyenler için birebir Python dersleri kapsamında hazırlanan diğer yazılara göz atmak iyi bir devam noktası olabilir.

Sık Sorulan Sorular

Class ile fonksiyon arasındaki temel fark nedir?

Fonksiyon tek bir işlemi yapıp sonuç döndürür ve kendi başına bir veri saklamaz. Class ise veriyi (attribute) ve bu veriyi işleyen davranışları (metot) bir arada tutar; ayrıca bu yapıdan birden fazla, birbirinden bağımsız nesne üretmene olanak verir.

self parametresini her metotta yazmak zorunda mıyım?

Evet, bir sınıfın içinde tanımlanan ve o sınıfın nesnesi üzerinden çalışması beklenen her metotta ilk parametre olarak self yazılır. Bu, Python'un o metodu hangi nesne üzerinden çalıştıracağını bilmesini sağlayan standart bir kuraldır.

__init__ metodunu tanımlamazsam ne olur?

Sınıfından yine nesne oluşturabilirsin, çünkü __init__ zorunlu değildir. Ancak nesne oluşturulurken otomatik olarak atanacak başlangıç verisi (isim, not gibi) olmaz; bu bilgileri nesne oluşturulduktan sonra ayrı ayrı elle atamak gerekir, bu da hata riskini artırır.

Bir sınıftan kaç tane nesne oluşturabilirim?

Sınırın yok. Aynı sınıftan istediğin kadar nesne oluşturabilirsin ve her biri kendi verisini bağımsız olarak taşır. Örneğin bir Ogrenci sınıfından yüzlerce farklı öğrenci nesnesi türetilebilir, her biri kendi ismini ve notunu ayrı ayrı saklar.

self ile normal bir değişkeni nasıl ayırt ederim?

self ile başlayan bir isim (self.isim gibi) nesnenin kendisine ait, nesne yaşadığı sürece hafızada kalan bir attribute'tur. self olmadan tanımlanan bir değişken ise sadece o metodun çalıştığı anda var olan, metot bittiğinde kaybolan yerel bir değişkendir.

OOP öğrenmeden önce fonksiyonlara hakim olmak şart mı?

Kesinlikle önerilir. Class içindeki metotlar özünde fonksiyonlardır; parametre alma, değer döndürme ve mantık kurma becerisi fonksiyonlarla kazanılır. Bu temel sağlam olmadan class'a geçmek, anlaşılmayan bir konunun üzerine bir konu daha eklemek olur.

Kalıtım gibi ileri konulara ne zaman geçmeliyim?

Class, nesne, self ve __init__ mantığını kendi başına kod yazarak, hatasız açıklayabildiğinde kalıtım ve diğer ileri OOP konularına geçmek için hazırsın demektir. Bu temelleri atlayarak ileri konulara geçmek genellikle kafa karışıklığıyla sonuçlanır.

Bu makaledeki bilgiler yeterli mi, daha fazla pratik nereden yapılır?

Bu yazı kavramsal temeli oturtmak için tasarlandı; gerçek kalıcılık ise bol pratikle gelir. Küçük sınıflar yazıp bozarak, hatalarını görerek ilerlemek en etkili öğrenme yoludur.

Class, nesne, self ve __init__ kavramlarını bir kez oturttuğunda, Python'da nesne yönelimli düşünmenin kapısı gerçek anlamda açılır. Bu temeller üzerine daha ileri konuları öğrenmek isteyenler, birebir ilerleyen ders yapısıyla Python özel ders programına göz atabilir.

Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

İlgili Eğitimler

Berk Keskin — Yazılım Geliştirici ve Eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; bugün öğrencinin seviyesine ve hedefine göre şekillenen sürdürülebilir öğrenme sistemleri tasarlıyor. 300'den fazla kişiye ezber değil, düşünerek kod yazmayı öğretti — Berk Akademi'de izlemeye değil üretmeye dayalı öğrenme kültürünü o kuruyor.

WhatsApp Hemen Ara