Ana içeriğe geç

Python Özel (Private) Metotlar Açıklandı

Python’daki özel metotları, sözdizimini, projelerinizde onları nasıl ve ne zaman kullanacağınızı örneklerle ve en iyi uygulamalarla öğrenin.
· 9 dk. oku

Yapay Zeka ile Keşfedin

Nesne Yönelimli Programlama (OOP), gerçek dünya varlıklarını modellemek için “nesneler” kullandığımız bir yazılım tasarım yaklaşımıdır. Bir nesne, veriler (öznitelikler) ve bu verilere etki eden işlevler (metotlar) içeren bir veri yapısıdır. Karmaşık sistemler nesnelerle daha kolay tasarlanabilir.

OOP’nin temel kavramlarını ve yazılım mühendisliği prensiplerini öğrenmek için Python ile nesne yönelimli programlama kursumuza başlayın.

Kapsülleme, OOP’nin temel bir kavramıdır. Bir nesnenin verilerini ve metotlarını bir arada tutmak ve ayrıntıları dış dünyadan gizlemek anlamına gelir. Kapsüllemeyi, kendi verileri ve onları işleme yöntemleri olan bir “kapsül” (nesne) oluşturma süreci olarak düşünebilirsiniz.

Kapsüllemenin başlıca amacı şunlardır:

  • Veriye doğrudan erişimi önlemek (veri bütünlüğü).
  • Yalnızca gerekli olanı göstermek suretiyle sistemi sadeleştirmek (soyutlama).

Özel metotlar, bir sınıfın iç uygulama ayrıntılarını gizleyerek bu kapsüllemeyi sağlamanın anahtarıdır.

Bir metodu özel yaptığınızda, diğer geliştiricilere bu metodun doğrudan erişim için tasarlanmadığını belirtmiş olursunuz. Bu, bir nesnenin iç durumunun yalnızca kontrollü yollarla değiştirilebilmesini sağlayarak hata ve sorunları önleyebilir.

Burada özel metotları tanıtacak, onları tanımlamanın sözdizimini, gerçek dünya örnekleriyle nasıl uygulanacağını ve kullanımına dair en iyi uygulamaları ele alacağız.

Özel (Private) Metotlar Nedir?

Nesne yönelimli programlamada (OOP) özel metotlar, yalnızca dahili kullanım için tasarlanmış sınıf içi işlevlerdir. Bir sınıfın işlevselliğini kapsüller ve iç işleyişinin dış etkileşimden korunmasını sağlar.

Bu kapsülleme, bir soyutlama katmanı sunarak sınıfın iç durum ve davranışını kontrol etmesine, ayrıca ona bağlı harici kodu etkilemeden uygulamasını değiştirmesine olanak tanır.

Python’da özel metotları belirtmek için yaygın kural, metodun adının başına tek alt çizgi (_) veya çift alt çizgi (__) eklemektir. Bu, metodun amaçlanan kapsamına dair geliştiricilere bir ipucu verir ve yalnızca bir konvansiyondur.

Bu konvansiyon bazı dillerdeki gibi katı gizlilik sağlamasa da, metodun amaçlanan kullanımını belirtmek için Python topluluğunda saygı duyulan bir pratiktir. İleride bu yönlere daha kapsamlı biçimde değineceğiz.

Özel Metotların Sözdizimi

Özel metotları tanımlamanın iki farklı yolu vardır; bunları örneklerle göreceğiz.

Fonksiyon adının önüne tek alt çizgi getirerek bir özel metod tanımlayabiliriz:

class MyClass:
   def _private_method(self):
       print("This is a private method")

Bu tanım, her ne kadar fonksiyon sınıfın dışından hâlâ erişilebilir olsa da (önerilmese de), yalnızca geliştiriciler için bir konvansiyondur.

Python’da sınıfları ilk kez duyuyorsanız, önce başlangıç seviyesindeki Sınıflar eğitimimize göz atmanızı öneririz.

Bir nesne oluşturalım ve oluşturduğumuz özel metoda erişmeyi deneyelim:

# Creating an object
obj = MyClass()

# Accessing from outside
obj._private_method()  # Not recommended to call directly, but possible

Python’da özel metotları çift alt çizgi ile tanımlamak için başka bir sözdizimi daha vardır. Şöyle görünür:

class MyClass:
   def __private_method(self):
       print("This is a private method")

obj = MyClass()
# obj.__private_method()  # This will raise an AttributeError

Sınıf dışından özel metoda erişmeye çalıştığımızda, AttributeError oluşur; bu da fonksiyon adı kullanılarak doğrudan erişilemeyeceğini gösterir.

Python’da özel metotların sözdizimini özetlersek:

  • Tek alt çizgi: yalnızca geliştiriciler için bir konvansiyondur, fonksiyondan dışarıdan erişilebilir.
  • Çift alt çizgi: yalnızca fonksiyon adıyla dışarıdan erişilemez. Yine de “İsim Çarpıtma (Name Mangling)” yoluyla erişilebilir; bunu bu eğitimin ilerleyen kısmında göreceğiz.

Python’da Özel Metotların Uygulanması

Gerçek dünyadan bir örnek olarak, bir kullanıcının finansal işlemlerini yönetmek için güvenli ve kullanıcı dostu bir BankAccount sınıfını ele alalım. Banka hesaplarının gereksinimleri şunlardır:

  • Sınıf, hesap sahibinin bakiyesini kapsüllemeli; para yatırma ve çekmeye izin verirken bakiyenin sınıf dışından doğrudan manipüle edilmesini engellemelidir.
  • Sınıf, bakiyeyi değiştirme mekanizmasını açığa çıkarmadan, alıcı hesabın bakiyesini güncelleyerek hesaplar arasında güvenli transferleri kolaylaştırmalıdır.
  • Çözüm, özellikle kapsülleme ve soyutlama prensiplerine uyacak şekilde, hesabın verilerinin bütünlüğünü korumalı ve hesapla etkileşim için net, basit bir arayüz sağlamalıdır.

Elbette bir banka hesabının bakiye sorgulama, para birimi dönüşümü ve faiz hesaplama gibi daha fazla işlevselliğe ihtiyacı vardır — ancak basit tutmak için bunları uygulamamızda göz ardı edeceğiz.

Şimdi bu çözümü uygulayalım ve kodu anlayalım.

class BankAccount:
   def __init__(self, account_holder, initial_balance=0):
       self.account_holder = account_holder
       self.__balance = initial_balance  # Private attribute

   def deposit(self, amount):
       if amount > 0:
           self.__balance += amount
           print(f"Deposited ${amount}. New balance: ${self.__balance}")
       else:
           print("Deposit amount must be positive.")

   def withdraw(self, amount):
       if 0 < amount <= self.__balance:
           self.__balance -= amount
           print(f"Withdrew ${amount}. New balance: ${self.__balance}")
       else:
           print("Insufficient funds or invalid amount.")

   def __update_balance(self, amount):  # Private method
       self.__balance += amount

   def transfer(self, amount, other_account):
       if 0 < amount <= self.__balance:
           self.withdraw(amount)
           other_account.__update_balance(amount)
           print(f"Transferred ${amount} to {other_account.account_holder}.")
       else:
           print("Insufficient funds or invalid amount.")

Önce, bir BankAccount nesnesinin gerektirdiği tüm davranış ve işlevleri saran bir BankAccountclass oluşturuyoruz.

BankAccount sınıfının özel bir __balance özniteliği ve özel bir __update_balance metodu vardır:

  • Özel değişken (__balance): Bu, mevcut hesap bakiyesini saklayan BankAccount sınıfının bir özniteliğidir. Adının başına iki alt çizgi (__) getirilerek özel olarak işaretlenmiştir. Bu, yalnızca sınıfın kendi içinde erişilmesi amaçlandığı anlamına gelir. Örneğin, deposit, withdraw ve __update_balance metotları tarafından değiştirilir. Bu özniteliğe dışarıdan erişim önerilmez.
  • Özel metod (__update_balance): Bu metodun amacı hesap bakiyesini güncellemektir. Bir transfer işlemi sırasında alıcı hesabın bakiyesini güncellemek için transfer metodu tarafından çağrılır. Burada özel bir metod kullanmak, bakiye güncelleme mantığını kapsüllemeye yardımcı olur ve bunun yalnızca sınıf tarafından tanımlanan kontrollü yollarla yapılabilmesini sağlar.

Yeni bir Python dosyası oluşturup yukarıdaki ve aşağıdaki kodları kopyalayıp yapıştırarak çalıştırabilir ve kendiniz görebilirsiniz.

# Using the Bank Account Solution
account1 = BankAccount("John Doe", 1000)
account2 = BankAccount("Jane Doe", 500)

account1.deposit(200)
account1.withdraw(100)
account1.transfer(300, account2)

Aşağıdaki çıktıyı göreceksiniz:

Deposited $200. New balance: $1200
Withdrew $100. New balance: $1100
Withdrew $300. New balance: $800
Transferred $300 to Jane Doe.

Tebrikler! Özel bir metod kullanarak kendi BankAccount çözümünüzü oluşturdunuz!

Çıktıya bakarak, para yatırma, çekme ve havale gibi olağan bankacılık işlemleri yapılırken bir banka hesabının beklenen mantıksal davranışının takip edildiğini görüyoruz.

__init__ metodu: özel bir metod mu?

Banka Hesabı örneğinde kullanılan __init__ metodunu muhtemelen fark ettiniz. Çift alt çizgi sözdizimini kullandığı için, bunun da özel bir metod olup olmadığını merak ediyor olabilirsiniz.

__init__ metodu, gizlilik için çift alt çizgiyle öneklenen metotlarla aynı şekilde özel bir metod olarak kabul edilmez.

Bunun yerine, dilde belirli bir amaca hizmet eden ve genellikle “dunder” ("double underscore"ın kısaltması) metod olarak anılan özel metotların bir parçasıdır. Bu tür özel metotlara __str__, __repr__ ve __del__ de örnek verilebilir.

Bu özel metodun örneğimizde nasıl kullanıldığını anlayalım:

class BankAccount:
   def __init__(self, account_holder, initial_balance=0):
       self.account_holder = account_holder
       self.__balance = initial_balance

Gördüğümüz gibi, __init__ metodu bir sınıfın kurucusudur. Sınıfın yeni bir örneği oluşturulduğunda otomatik olarak çağrılır ve nesnenin özniteliklerini başlatmak için kullanılır. BankAccount sınıfında __init__ metodu, account_holder ve __balance özniteliklerine başlangıç değerleri atamak için kullanılır.

İleri Kavramlar: Python’da İsim Çarpıtma (Name Mangling)

Tanımımızın başlarında, Python’da özel metotların yalnızca bir konvansiyon olduğunu ve dilin, diğer programlama dillerinin aksine, gizliliği katı biçimde zorunlu kılmadığını belirtmiştik.

Nitekim tek alt çizgi kullanıldığında özel metotlara doğrudan erişilebildiğini, çift alt çizgi kullanıldığında ise erişimin kısıtlandığını gördük.

Peki neden? Python’daki “isim çarpıtma” denilen bir kavram yüzünden.

Bir öznitelik adının başına çift alt çizgi getirdiğinizde, Python bu adı otomatik olarak, orijinal öznitelik adının başına tek alt çizgi ve sınıf adını ekleyerek değiştirir.

Bu değiştirilmiş ad, özniteliğin sınıf içinde dahili olarak depolandığı addır. Adın bu şekilde değiştirilmesi sürecine isim çarpıtma denir.

İsim çarpıtma iki nedenle yararlıdır:

  • İsim çakışmalarını önleme: Kalıtımda, bir alt sınıf üst sınıfındaki bir öznitelikle aynı ada sahip bir öznitelik tanımlarsa, ikisi çakışır. İsim çarpıtma, adların her sınıfa özgü olmasını sağlayarak bu sorunu önlemeye yardımcı olur.
  • Belirli bir gizlilik derecesi: Python gerçek anlamda özel özniteliklere sahip olmasa da, isim çarpıtma, özniteliklerin sınıf dışından daha az erişilebilir olmasını sağlayarak belirli bir gizlilik derecesi sunar.

Daha iyi anlamak için bir örnek görelim.

class MyClass:
   def __init__(self):
       self.__private_attribute = "I am private"

   def __private_method(self):
       print("This is a private method")

obj = MyClass()
print(obj.__private_attribute)  # This will raise an AttributeError

Bu örnekte, __private_attribute ve __private_method isim çarpıtmaya tabidir. Dahili olarak sırasıyla _MyClass__private_attribute ve _MyClass__private_method olarak depolanırlar. Sınıf dışından orijinal adlarıyla erişmeye çalışmak bir AttributeError ile sonuçlanır.

Bununla birlikte, çarpıtılmış adlarını kullanarak yine de erişebilirsiniz:

print(obj._MyClass__private_attribute)  # This will print "I am private"
obj._MyClass__private_method()  # This will print "This is a private method"

İsim çarpıtma öznitelikleri daha az erişilebilir kılarken, bunun Python’da gizliliği sağlamak için kusursuz bir yol olmadığını unutmamak önemlidir. Daha çok, bir özniteliğin sınıf içinde dahili kullanım için tasarlandığını belirtmek üzere kullanılan bir konvansiyondur.

Özel Metot ve Değişkenleri Kullanma İçin En İyi Uygulamalar

Özel metot ve değişkenlerden etkin biçimde yararlanmak, belirli en iyi uygulamalara bağlı kalmayı gerektirir. Bu uygulamalar, kodunuzun yalnızca işlevsel değil, aynı zamanda anlaşılır, sürdürülebilir ve güvenli olmasını sağlar.

İzlemeniz gereken bazı en iyi uygulamalar şunlardır:

  • “Korumalı” öznitelikler için tek alt çizgi kullanın. Bir öznitelik veya metodun sınıf ve alt sınıfları içinde kullanılmasının amaçlandığını, ancak harici kullanım için tasarlanmadığını belirtmek istiyorsanız başına tek alt çizgi (_) ekleyin. Bu, Python’da öznitelik veya metodun “korumalı” olduğu ve doğrudan erişilmemesi gerektiğini ifade eden bir konvansiyondur.
  • “Özel” öznitelikler için çift alt çizgi kullanın. Bir öznitelik veya metodun sınıf dışından daha az erişilebilir olmasını, kazara değiştirilmesini veya kullanılmasını önlemek istiyorsanız başına çift alt çizgi (__) ekleyin. Bu, isim çarpıtmayı tetikler ve özniteliğe veya metoda sınıf dışından erişimi zorlaştırır (imkansız değil).
  • Dahili mantık için özel metotlar kullanın. (Tek veya çift alt çizgi önekli) özel metotlar, sınıfınızın dahili mantığını kapsüllemenin harika bir yoludur. Sınıfın uygulamasına özgü olan ve sınıfın herkese açık arayüzünün parçası olarak ortaya çıkarılmaması gereken görevleri yerine getirmek için kullanın.

Son olarak, kodlama en iyi uygulamalarınızda tutarlı olmak önemlidir. Adlandırma konvansiyonlarına bağlı kalın ve bunları kod tabanınız genelinde tutarlı şekilde kullanın. Bu, kodunuzun hem diğer geliştiriciler hem de gelecekteki kendiniz için daha anlaşılır ve sürdürülebilir olmasını sağlar.

Sonuç

Bu eğitimde özel metotların arkasındaki kavramları, sözdizimini ve ne zaman kullanılabileceklerini öğrendiniz. Ayrıca, bir sonraki kodlama projenizde bunları nasıl kullanabileceğinizi gösteren birden çok örnek gördük. Son olarak, kullanırken akılda tutulması gereken bazı en iyi uygulamalara baktık.

Daha fazla öğrenmek için Python Programlama Yetenek Yolunu ve Python’da Nesne Yönelimli Programlama kursunu inceleyebilirsiniz.

Arunn Thevapalan

Yazar

Arunn Thevapalan

Kıdemli veri bilimcisi olarak, işletmelerin veriye dayalı daha iyi kararlar almasına yardımcı olmak için büyük ölçekli makine öğrenimi çözümleri tasarlıyor, geliştiriyor ve uyguluyorum. Veri bilimi yazarı olarak, öğrendiklerimi, kariyer tavsiyelerimi ve ayrıntılı uygulamalı eğitimleri paylaşıyorum.

Konular

İlgili