Python’da “Sınıf (Class)” Oluşturma ve “Nesne (Object)” Kullanımı

Bu yazımızda, Python’da nasıl sınıf (Class) oluşturulacağını ve bu sınıflardan nasıl nesne (Object) türetileceğini detaylı bir şekilde ele alacağız. Özellikle nesne yönelimli programlamanın temel kavramlarından olan “sınıf ve nesne” yapıları, uygulama geliştirme süreçlerinde oldukça kritik bir rol oynamaktadır. Bu yüzden oldukça önemlidir.

Python’da “Sınıf (Class)” Oluşturmak

Python’da sınıflar, belirli bir nesne grubunun özelliklerini ve işlevlerini modellemek için kullanılır. Bu yönüyle sınıfı, şablon görevi gören taslaklar (blueprint) olarak tanımlayabiliriz. Bu taslaklardan faydalanarak oluşturduğumuz yapılarak ise nesne adı verilir.

Sınıfları ve nesneleri anlamak için onları yemek tarifleriyle hazırlanan yemeklere benzetebiliriz. Sınıf (class), bir yemek tarifi gibidir; hangi malzemelerin kullanılacağını, ne sıra ile ekleneceğini ve nasıl bir işlem yapılacağını belirtir. Ancak bu tarifteki ölçülere ve adımlara ne kadar sadık kalırsak kalalım, her seferinde hazırladığımız yemek bir öncekine göre biraz farklı olabilir. İşte bu farklılıkları temsil eden her bir yemek, birer nesne (object) olup, aynı sınıftan (tariften) türetilmiştir. Yani, sınıf soyut bir yapıyı temsil ederken, nesneler bu yapıya somut bir form kazandırır ve her biri kendi benzersiz özellikleriyle ayrılır.

Python’da sınıf oluşturmak için, kelimenin İngilizce anlamı olan, class anahtar kelimesinden faydalanırız. Yalnız diğer anahtar kelimelerden farklı olarak adlandırmaya her zaman büyük bir harfle başlamamız gerekir ve adlandırmayı “PascalCase” şeklinde yapmamız gerekir. Örneğin:

Yeri gelmişken örneğimizde de kullandığımız pass anahtar kelimesinin ne anlama geldiğini ve niye kullanıldığını açıklayalım:

Bir sınıf veya fonksiyon tanımı oluşturduğunuzda, Python’da bu blokların girintili bir şekilde içeriğe sahip olması beklenir. Ancak bazen içerik yazmadan sadece sınıf veya fonksiyonun iskeletini (yapısını) oluşturmak istersiniz. İşte bu gibi durumlarda pass kelimesini kullanarak Python’a “bu blok için şimdilik hiçbir şey yapma” mesajını veririz.

“Peki, hiç bir şey yazmasam olmaz mıydı? Yani ille de “pass” yazmak zorunda mıyım?” gibi bir soru sorabilirisiniz. Evet zorundayız. Python, sınıf bloğu içerisinde herhangi bir içerik bulamadığında eğer pass yazılmamışsa “IndentationError: expected an indented block” hatasını verecektir.

Bir sınıfın içerisine, o sınıfı tanımlayan özellikler (nitelikler) ve bu özellikler üzerinde işlem yapabilecek fonksiyonlar (metodlar) ekleyebiliriz. Nitelikler, sınıfın özelliklerini veya durumunu temsil ederken; metodlar, sınıfın ne tür eylemler gerçekleştirebileceğini tanımlar. Ayrıca, sınıfın başlangıçta hangi değerlere sahip olacağını belirtmek için __init__ adında özel bir başlatma metodunu da tanımlayabiliriz. Bu yapı, sınıfımızın bir nesnesi oluşturulduğunda otomatik olarak çağrılır. Bunların yanı sıra, sınıf içerisinde sınıf değişkenleri, sınıf metodları ve statik metodlar gibi daha ileri seviye özellikleri de ekleyebiliriz.

Özellik ve Metotlar

İşe ilk olarak aşina olduğumuz değişken (variable) ve fonksiyon (function) kavramlarından başlayalım. Python’da sınıf içerisinde tanımladığımız değişkenlerenitelik” ya da “özellik” (attribute) adını veririz. Bu nitelikler, sınıfın ya da sınıfın örneklerinin durumunu ve sahip olduğu bilgileri temsil eder. Örneğin, bir Kisi sınıfının içerisinde ad ve yas gibi nitelikler bulunabilir.

Bunun yanında, sınıf içerisinde tanımladığımız fonksiyonlara ise “metod” (method) diyoruz. Metodlar, sınıfın ya da sınıfın örneklerinin gerçekleştirebileceği eylemleri veya işlemleri tanımlar. Yine Kisi sınıfını düşünerek, bu sınıf içerisinde kişinin selam vermesini sağlayan selam_ver adlı bir metod tanımlanabilir. Bu terminoloji, nesne yönelimli programlamada daha tutarlı ve anlamlı bir dil oluşturmak için kullanılır.

  • değişken (variable) ➡️ nitelik/özellik (attribute)
  • fonksiyon (function) ➡️ metot/yöntem (method)

Sınıf içerisindeki değişkenler ve fonksiyonlar için farklı adlandırmalara sahip olmamızın temel nedeni, nesne yönelimli programlamanın (OOP) sunduğu yapısal ve soyutlamaya dayalı yaklaşımı uyguladığımızı daha iyi ifade etmektir.

Haliyle, nitelikler (attributes), bir sınıfın veya onun örneklerinin sahip olduğu özellikleri veya durumu temsil eder. Örneğin, bir Araba sınıfı için nitelikler renk, marka veya model olabilir. Buna karşılık metotlar (methods) ise bu nitelikler üzerinde işlem yapar veya sınıfın (veya onun örneklerinin) nasıl davrandığını tanımlar. Yine Araba sınıfını örnek alacak olursak, hizlan, yavasla veya korna_cal gibi metotlar bu sınıfın davranışlarını temsil eder. Örneğin:

Sınıfımızdaki marka, model, renk ve hiz nitelikleri (veya özellikleri) temsil eder. Bunlar sınıfın durumunu veya değerlerini saklar. Buna karşılık hizlan, yavasla ve korna_cal sınıfımızın metotlarıdır. Bunlar sınıfın (veya onun örneklerinin) nasıl davrandığını belirtir ve genellikle bir işlevsellik sağlar. Kodu çalıştırmak için: Trinket

“self” Kavramı

Yukarıdaki örneğimzde fark edileceği üzere “self” adında bir kavram görülmektedir. Python’da, self terimi birçok kişi için ilk başta karmaşık gelebilir ama aslında oldukça basit bir konsepti ifade eder.

Bir sınıf içerisinde, metotların (yani o sınıf içerisinde tanımlanan fonksiyonların) o sınıfın niteliklerine (yani değişkenlerine) veya diğer metotlarına erişebilmesi için bir araca ihtiyaçları vardır. İşte bu araç, “self” kelimesidir.

Örneğimizdeki gibi bir “Araba” sınıfınız olduğunu düşünelim ve bu sınıf içerisinde “marka” adında bir nitelik (değişken) ve “korna_cal” adında bir metot (fonksiyon) tanımladınız. “korna_cal” fonksiyonunun, “marka” değişkenini kullanarak hangi arabanın korna çaldığını söylemesini istiyorsunuz. İşte bu fonksiyonun, “marka” değişkenine erişebilmesi için “self” kelimesini kullanması gerekiyor. “self.marka” şeklinde bir ifadeyle, “şu anki arabanın markası”na erişim sağlanır.

Bu yüzden, “self”, sınıf içerisinde tanımlanan metotların, o sınıfın niteliklerine veya diğer metotlarına erişmelerini sağlayan bir anahtardır. Yani kabaca; sınıfın içindekileri, sınıfın içindekilere bağlayan mekanizmadır.

“__init__ ()” Fonksiyonu

Verdiğimiz örneği ele alalım. Burada bir Araba nesnesi oluşturuyoruz ve ardından bu arabaya marka, model ve renk atıyoruz. Fakat bu yaklaşım, özellikle daha büyük projelerde veya çok sayıda araba nesnesi oluşturduğumuzda bizi yorabilir. Her bir araba için marka, model ve renk bilgisini tek tek giriyor olmamız, hem zamanımızı alacak hem de bazen unutkanlıkla bazı bilgileri atlamamıza yol açabilir.

Ayrıca, bir arabayı temsil eden bu sınıfta, belki her arabanın başlangıçta belirli özelliklere sahip olmasını isteyebiliriz. Örneğin, her arabayı oluşturduğumuzda hızının sıfır olmasını garantileyebiliriz.

Bu tür bir otomasyonu ve başlangıç değerlerini belirlemeyi kolaylaştırmak için, __init__ fonksiyonunu kullanmaya başlarız. Bu fonksiyon, bir Araba nesnesi oluşturulduğunda otomatik olarak çağrılır. Yani, bir Araba nesnesi oluşturduğumuz anda, bu arabaya marka, model, renk ve diğer başlangıç değerlerini hemen atayabiliriz.

Bu yaklaşım sayesinde, her yeni nesne oluşturduğumuzda tekrar tekrar aynı bilgileri girmekten kurtuluruz ve nesnelerimizin daha tutarlı bir şekilde başlatılmasını sağlarız. Örneğimizi yeniden yazalım:

Bu yaklaşımla, Araba sınıfından bir nesne oluştururken doğrudan marka, model ve renk bilgisini vererek nesneyi başlatıyoruz. Bu, kodun daha okunabilir olmasını sağlar ve potansiyel olarak hata yapma riskimizi azaltır. Ayrıca, hiz özelliğini varsayılan olarak 0 değeri ile başlattık, böylece bu değeri her oluşturma işlemi sırasında belirtmemiz gerekmiyor.

Bu arada, yeri gelmişken self kelimesi yerine farklı adlandırmalar da yapılabildiğini söylemek isterim. Aşağıdaki örnekte bunu self yerine oyuncu yazarak gerçekleştirdik:

Python’da “self” kelimesi, sadece bir gelenek olarak kullanılır ve pekala başka herhangi bir kelimeyle değiştirilebilir. Ancak, “self” kelimesi Python topluluğunda yaygın olarak kabul görmüştür, bu yüzden bunu kullanmaya özen gösterin. Kodu çalıştırmak için: Trinket

Python’da Nesne Özelliklerini Değiştirmek

= işareti ile kolayca değiştirilmek istenen nesne özellikleri değiştirilebilir:

Bu örnekte, “Lionel” olarak tanımlanan futbolcu1 adlı nesnenin ad niteliğini, “=” işareti kullanarak “Cristiano” olarak değiştirdik. Bu, obje yönelimli programlamanın esnekliğini gösteren bir özelliktir. Ancak, doğrudan niteliklere erişip değiştirme işlemi bazen istenmeyen sonuçlara yol açabilir. Bu tür olası problemleri önlemek için bazen “private” (özel) nitelikler veya “getter” ve “setter” metotları kullanılır. Ancak bu, başka bir konunun detayıdır. Kodu çalıştırmak için: Trinket

Nesnenin Bir Özelliğini Ya Da Nesneyi Silmek

Eğer bir nesnenin belirli bir niteliğini silmek istiyorsak, bu niteliğe del anahtar kelimesi ile erişebiliriz. Bakınız:

Eğer bir nesneyi komple silmek ve bellekten kaldırmak istiyorsak, bu sefer de nesneye del anahtar kelimesi ile erişiriz. Bakınız:

Python’da İlerin Düzey Sınıf Kavramları

Nesne yönelimli programlama Python’da dört ana kavrama ayrılır. Her biri ayrı yazılarda detaylarıyla incelenmiştir. Bakınız:

  1. Inheritance (Miras): Bir sınıfın, başka bir sınıftan özelliklerini (nitelikler ve metotlar) miras almasına denir.
  2. Encapsulation (Kapsülleme): Veriyi ve işlevselliği bir araya getirerek erişimi kısıtlar.
  3. Polymorphism (Çok biçimlilik): Farklı sınıfların, aynı arayüze sahip olmasına rağmen farklı işlevselliğe sahip olması durumunu ifade eder. Yani aynı metot adı, farklı sınıflarda farklı işler yapabilir.
  4. Abstraction (Soyutlama): Kompleks bir sistemi, temel bileşenlerine ayırır. Soyut sınıflar ve soyut metotlar ile gerçeklenir.

İlgili Makaleler

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Başa dön tuşu