Python’da Kapsülleme (Encapsulation): Veri Gizleme ve Kontrollü Erişim

Nesne Yönelimli Programlama (OOP), yazılımı daha modüler, anlaşılır ve yönetilebilir hale getirmek için güçlü prensipler sunar. Bu prensiplerden biri olan Kapsülleme (Encapsulation), OOP’nin temel yapı taşlarından biridir ve veri ile o veriyi işleyen metotların mantıksal bir bütünlük içinde bir araya getirilmesini ifade eder. Ancak kapsülleme sadece bir araya getirmekten daha fazlasıdır; aynı zamanda nesnenin iç detaylarını dış dünyadan koruma ve kontrollü erişim sağlama mekanizmalarını da içerir. Kapsülleme, bir sınıfın niteliklerini (verilerini) ve metotlarını (davranışlarını) bir “kapsül” içine alarak, bu iç yapıyı doğrudan dış müdahalelerden korumayı hedefler. Dış kodun, nesnenin iç durumunu rastgele değiştirmesini engeller ve bunun yerine, nesnenin durumuyla etkileşim kurmak için iyi tanımlanmış arayüzler (genellikle public metotlar veya property’ler) sunar. Bu, “bilgi gizleme” (information hiding) veya “veri gizleme” (data hiding) olarak da bilinir. Bu rehberde, kapsülleme kavramını derinlemesine inceleyeceğiz. Ne anlama geldiğini, Python’da nasıl uygulandığını (özellikle Python’un konvansiyonlara dayalı yaklaşımını), tek alt çizgi () ve çift alt çizgi (_) kullanımının anlamını, kontrollü erişim için getter/setter metotları ve Pythonic bir çözüm olan @property dekoratörünü ele alacağız. En önemlisi, kapsüllemenin yazılım tasarımına sağladığı sayısız faydayı örneklerle açıklayacağız. Bölüm 1: Kapsülleme Nedir? Temel Fikir Kapsüllemeyi anlamanın en iyi yollarından biri analojiler kullanmaktır: İlaç Kapsülü Analojisi: Bir ilaç kapsülünü düşünün. İçindeki etken maddeler (veriler) dış koruyucu katman (sınıf) tarafından bir arada tutulur. Kapsülün amacı, ilacın doğru şekilde çalışmasını sağlamak ve içindeki maddelerin dış etkenlerden korunmasını sağlamaktır. Kapsülü yuttuğunuzda (nesneyi kullandığınızda), ilacın nasıl çalıştığının tüm detaylarını bilmenize gerek yoktur; sadece beklenen etkiyi (arayüzü) bilirsiniz. Araba Motoru Analojisi: Arabanızı kullanırken gaz pedalına basarsınız (metodu çağırırsınız) ve araba hızlanır. Motorun içindeki pistonların, valflerin, yakıt enjeksiyonunun nasıl çalıştığının tüm karmaşık detaylarını (iç durum ve mekanizmalar) bilmek zorunda değilsiniz. Üretici, motoru bir “kapsül” içine alarak karmaşıklığı gizlemiş ve size basit bir arayüz (gaz pedalı, fren pedalı, direksiyon) sunmuştur. Bu arayüz üzerinden motorla güvenli ve kontrollü bir şekilde etkileşim kurarsınız. Motorun iç parçalarına doğrudan müdahale etmeniz beklenmez ve genellikle istenmez. Bu analojilerden yola çıkarak kapsüllemenin iki ana yönünü görebiliriz: Paketleme (Bundling): İlişkili verileri (nitelikler) ve bu veriler üzerinde çalışan fonksiyonları (metotlar) mantıksal bir birim olan sınıf içinde bir araya getirmek. Bu, kodun organizasyonunu artırır. Bilgi/Veri Gizleme (Information/Data Hiding): Nesnenin iç uygulama detaylarını (internal state ve implementation details) dış dünyadan gizlemek. Dış kodun, nesnenin verilerine yalnızca nesnenin izin verdiği yollarla (genellikle public metotlar aracılığıyla) erişmesini ve değiştirmesini sağlamak. Bu, nesnenin bütünlüğünü korur ve kontrolü sağlar. Temel amaç, bir nesnenin durumunu (state) korumak ve bu durumun sadece iyi tanımlanmış, kontrollü yollarla değiştirilebilmesini sağlamaktır. Böylece nesnenin her zaman geçerli ve tutarlı bir durumda kalması hedeflenir. Bölüm 2: Neden Kapsülleme Kullanılır? Faydaları Kapsülleme, sadece teorik bir prensip değil, aynı zamanda yazılım geliştirmede somut faydalar sağlayan pratik bir yaklaşımdır. İşte kapsüllemenin başlıca faydaları: Veri Bütünlüğü ve Güvenlik (Data Integrity & Security): Nesnenin iç verilerine doğrudan erişimi kısıtlayarak, bu verilerin yanlışlıkla veya kasıtlı olarak geçersiz bir duruma getirilmesini önler. Örneğin, bir Hesap nesnesinin bakiyesinin negatif olmasını engelleyen kurallar, kapsülleme sayesinde (örneğin para_cek metodu içinde) uygulanabilir. Dışarıdan hesap._bakiye = -500 gibi bir atamanın önüne geçilir (veya en azından zorlaştırılır/işaretlenir). Esneklik ve Bakım Kolaylığı (Flexibility & Maintainability): Bu, kapsüllemenin en önemli faydalarından biridir. Nesnenin iç uygulama detayları (bir verinin nasıl saklandığı, bir işlemin nasıl yapıldığı) dış dünyadan gizlendiği için, bu iç detayları daha sonra değiştirebilirsiniz ve bu değişiklik, nesnenin public arayüzünü (dışarıya açık metotlarını) kullanan diğer kodları etkilemez (eğer arayüz aynı kalıyorsa). Örneğin, başlangıçta veriyi bir listede saklarken daha sonra daha verimli bir veri yapısına geçebilirsiniz; public metotlar aynı kaldığı sürece bu değişiklik dış kodu bozmaz. Bu, bakım maliyetini düşürür ve sistemi geliştirmeyi kolaylaştırır. Modülerlik (Modularity): Her sınıf, kendi verileri ve davranışları ile birlikte bağımsız, kendi kendine yeten bir modül gibi davranır. Bu, programın farklı parçalarını ayrı ayrı geliştirmeyi, test etmeyi ve yönetmeyi kolaylaştırır. Azaltılmış Karmaşıklık (Reduced Complexity): Bir sınıfı kullanan gelişt

Apr 9, 2025 - 12:29
 0
Python’da Kapsülleme (Encapsulation): Veri Gizleme ve Kontrollü Erişim

Nesne Yönelimli Programlama (OOP), yazılımı daha modüler, anlaşılır ve yönetilebilir hale getirmek için güçlü prensipler sunar. Bu prensiplerden biri olan Kapsülleme (Encapsulation), OOP’nin temel yapı taşlarından biridir ve veri ile o veriyi işleyen metotların mantıksal bir bütünlük içinde bir araya getirilmesini ifade eder. Ancak kapsülleme sadece bir araya getirmekten daha fazlasıdır; aynı zamanda nesnenin iç detaylarını dış dünyadan koruma ve kontrollü erişim sağlama mekanizmalarını da içerir.

Kapsülleme, bir sınıfın niteliklerini (verilerini) ve metotlarını (davranışlarını) bir “kapsül” içine alarak, bu iç yapıyı doğrudan dış müdahalelerden korumayı hedefler. Dış kodun, nesnenin iç durumunu rastgele değiştirmesini engeller ve bunun yerine, nesnenin durumuyla etkileşim kurmak için iyi tanımlanmış arayüzler (genellikle public metotlar veya property’ler) sunar. Bu, “bilgi gizleme” (information hiding) veya “veri gizleme” (data hiding) olarak da bilinir.

Bu rehberde, kapsülleme kavramını derinlemesine inceleyeceğiz. Ne anlama geldiğini, Python’da nasıl uygulandığını (özellikle Python’un konvansiyonlara dayalı yaklaşımını), tek alt çizgi () ve çift alt çizgi (_) kullanımının anlamını, kontrollü erişim için getter/setter metotları ve Pythonic bir çözüm olan @property dekoratörünü ele alacağız. En önemlisi, kapsüllemenin yazılım tasarımına sağladığı sayısız faydayı örneklerle açıklayacağız.

Bölüm 1: Kapsülleme Nedir? Temel Fikir
Kapsüllemeyi anlamanın en iyi yollarından biri analojiler kullanmaktır:

İlaç Kapsülü Analojisi: Bir ilaç kapsülünü düşünün. İçindeki etken maddeler (veriler) dış koruyucu katman (sınıf) tarafından bir arada tutulur. Kapsülün amacı, ilacın doğru şekilde çalışmasını sağlamak ve içindeki maddelerin dış etkenlerden korunmasını sağlamaktır. Kapsülü yuttuğunuzda (nesneyi kullandığınızda), ilacın nasıl çalıştığının tüm detaylarını bilmenize gerek yoktur; sadece beklenen etkiyi (arayüzü) bilirsiniz.

Araba Motoru Analojisi: Arabanızı kullanırken gaz pedalına basarsınız (metodu çağırırsınız) ve araba hızlanır. Motorun içindeki pistonların, valflerin, yakıt enjeksiyonunun nasıl çalıştığının tüm karmaşık detaylarını (iç durum ve mekanizmalar) bilmek zorunda değilsiniz. Üretici, motoru bir “kapsül” içine alarak karmaşıklığı gizlemiş ve size basit bir arayüz (gaz pedalı, fren pedalı, direksiyon) sunmuştur. Bu arayüz üzerinden motorla güvenli ve kontrollü bir şekilde etkileşim kurarsınız. Motorun iç parçalarına doğrudan müdahale etmeniz beklenmez ve genellikle istenmez.

Bu analojilerden yola çıkarak kapsüllemenin iki ana yönünü görebiliriz:

Paketleme (Bundling): İlişkili verileri (nitelikler) ve bu veriler üzerinde çalışan fonksiyonları (metotlar) mantıksal bir birim olan sınıf içinde bir araya getirmek. Bu, kodun organizasyonunu artırır.
Bilgi/Veri Gizleme (Information/Data Hiding): Nesnenin iç uygulama detaylarını (internal state ve implementation details) dış dünyadan gizlemek. Dış kodun, nesnenin verilerine yalnızca nesnenin izin verdiği yollarla (genellikle public metotlar aracılığıyla) erişmesini ve değiştirmesini sağlamak. Bu, nesnenin bütünlüğünü korur ve kontrolü sağlar.
Temel amaç, bir nesnenin durumunu (state) korumak ve bu durumun sadece iyi tanımlanmış, kontrollü yollarla değiştirilebilmesini sağlamaktır. Böylece nesnenin her zaman geçerli ve tutarlı bir durumda kalması hedeflenir.

Bölüm 2: Neden Kapsülleme Kullanılır? Faydaları
Kapsülleme, sadece teorik bir prensip değil, aynı zamanda yazılım geliştirmede somut faydalar sağlayan pratik bir yaklaşımdır. İşte kapsüllemenin başlıca faydaları:

Veri Bütünlüğü ve Güvenlik (Data Integrity & Security): Nesnenin iç verilerine doğrudan erişimi kısıtlayarak, bu verilerin yanlışlıkla veya kasıtlı olarak geçersiz bir duruma getirilmesini önler. Örneğin, bir Hesap nesnesinin bakiyesinin negatif olmasını engelleyen kurallar, kapsülleme sayesinde (örneğin para_cek metodu içinde) uygulanabilir. Dışarıdan hesap._bakiye = -500 gibi bir atamanın önüne geçilir (veya en azından zorlaştırılır/işaretlenir).
Esneklik ve Bakım Kolaylığı (Flexibility & Maintainability): Bu, kapsüllemenin en önemli faydalarından biridir. Nesnenin iç uygulama detayları (bir verinin nasıl saklandığı, bir işlemin nasıl yapıldığı) dış dünyadan gizlendiği için, bu iç detayları daha sonra değiştirebilirsiniz ve bu değişiklik, nesnenin public arayüzünü (dışarıya açık metotlarını) kullanan diğer kodları etkilemez (eğer arayüz aynı kalıyorsa). Örneğin, başlangıçta veriyi bir listede saklarken daha sonra daha verimli bir veri yapısına geçebilirsiniz; public metotlar aynı kaldığı sürece bu değişiklik dış kodu bozmaz. Bu, bakım maliyetini düşürür ve sistemi geliştirmeyi kolaylaştırır.
Modülerlik (Modularity): Her sınıf, kendi verileri ve davranışları ile birlikte bağımsız, kendi kendine yeten bir modül gibi davranır. Bu, programın farklı parçalarını ayrı ayrı geliştirmeyi, test etmeyi ve yönetmeyi kolaylaştırır.
Azaltılmış Karmaşıklık (Reduced Complexity): Bir sınıfı kullanan geliştiricinin, sınıfın nasıl çalıştığının tüm iç detaylarını bilmesine gerek yoktur. Sadece sınıfın sunduğu public arayüzü (hangi metotları çağırabileceğini, hangi parametreleri beklediğini) bilmesi yeterlidir. Bu, bilişsel yükü azaltır ve sınıfın kullanımını basitleştirir.
Kod Yeniden Kullanılabilirliği (Code Reusability): İyi kapsüllenmiş sınıflar, farklı projelerde veya aynı projenin farklı bölümlerinde daha kolay yeniden kullanılabilir, çünkü iç işleyişleri dış bağımlılıklardan büyük ölçüde yalıtılmıştır.
Daha Kolay Hata Ayıklama (Easier Debugging): Bir nesnenin durumu yalnızca kendi metotları tarafından değiştirilebildiğinden, bir hata oluştuğunda sorunun kaynağını bulmak genellikle daha kolaydır. Hatanın büyük olasılıkla o nesnenin metotlarından birinde olduğu varsayılabilir.
Kontrollü Erişim (Controlled Access): Verilere erişimi metotlar aracılığıyla sağlayarak, verilere erişildiğinde veya veriler değiştirildiğinde ek işlemler (loglama, doğrulama, başka nesneleri bilgilendirme vb.) yapma imkanı doğar.
Bölüm 3: Python’da Kapsülleme Uygulamaları: Konvansiyonlar ve Mekanizmalar
Diğer bazı OOP dillerinin (Java, C++, C# gibi) aksine, Python’da nitelikleri veya metotları gerçekten “özel” (private) veya “korumalı” (protected) yapan anahtar kelimeler yoktur. Python’un felsefesi, geliştiricilere güvenir (“We are all consenting adults here”) ve katı kısıtlamalar yerine konvansiyonlar (gelenekler) kullanır.

Python’da kapsüllemeyi uygulamak için kullanılan temel yaklaşımlar şunlardır:

3.1. Public Üyeler (Public Members)
Tanım: Herhangi bir alt çizgi () ile başlamayan tüm nitelikler ve metotlar public olarak kabul edilir.
Amaç: Sınıfın dış dünya ile etkileşim kurmasını sağlayan resmi arayüzüdür. Bu üyelere sınıf dışından doğrudan erişilmesi beklenir ve güvenlidir.
Erişim: nesne.public_nitelik, nesne.public_metot() şeklinde erişilir.
class PublicOrnek:
def __init
(self, deger):
self.gorunur_veri = deger # Public nitelik
def islem_yap(self): # Public metot
print(f"Görünür veri ile işlem yapılıyor: {self.gorunur_veri}")
nesne = PublicOrnek(100)
print(nesne.gorunur_veri) # Dışarıdan erişim normal
nesne.gorunur_veri = 200 # Dışarıdan değiştirme normal
nesne.islem_yap()
3.2. “Korumalı” Üyeler: Tek Alt Çizgi Konvansiyonu (_protected)
Tanım: İsimleri tek bir alt çizgi ile başlayan nitelikler ve metotlar (örn: self._bakiye, def _yardimci_fonksiyon(self):).
Amaç: Bu bir konvansiyondur, Python tarafından zorlanan bir kısıtlama değildir. Anlamı şudur: “Bu üye, sınıfın iç implementasyonunun bir parçasıdır ve dışarıdan doğrudan erişilmesi veya değiştirilmesi genellikle istenmez. Eğer erişirseniz veya değiştirirseniz, ileride sınıfın iç yapısı değiştiğinde kodunuzun bozulma riski size aittir.”
Erişim: Teknik olarak public üyeler gibi nesne._korumali_nitelik veya nesne._korumali_metot() şeklinde erişilebilir. Python bunu engellemez.
Kullanım Alanları:
Sınıfın iç işleyişi için kullanılan ancak dış arayüzün parçası olması gerekmeyen yardımcı metotlar veya durum değişkenleri.
Alt sınıfların erişmesi veya override etmesi beklenen ancak sınıfın genel kullanıcıları tarafından doğrudan çağrılmaması gereken metotlar/nitelikler.
class KorumaliOrnek:
def __init
_(self, ilk_deger):
self._gizli_sayac = ilk_deger # Korumalı nitelik (konvansiyon)
def _sayaci_arttir(self, miktar=1): # Korumalı metot (konvansiyon)
self._gizli_sayac += miktar
print(f"(İçeriden) Sayaç artırıldı: {self._gizli_sayac}")
def public_islem(self, artis):
# Public metot, içerdeki korumalı metodu kullanabilir
print("Public işlem başlıyor...")
self._sayaci_arttir(artis)
print("Public işlem bitti.")
def sayaci_goster(self):
return self._gizli_sayac
kor_nesne = KorumaliOrnek(10)
kor_nesne.public_islem(5)
print(f"Sayaç değeri: {kor_nesne.sayaci_goster()}")

Dışarıdan erişim MÜMKÜN ama KAÇINILMALI!

print(f"Dışarıdan gizli_sayac erişimi: {kor_nesne._gizli_sayac}")
kor_nesne._gizli_sayac = 1000 # Doğrudan müdahale (kötü pratik)
print(f"Doğrudan müdahale sonrası sayaç: {kor_nesne.sayaci_goster()}")
kor_nesne._sayaci_arttir(1) # Korumalı metodu dışarıdan çağırmak (kötü pratik)
3.3. “Özel” Üyeler: Çift Alt Çizgi ve İsim Karmaşası (
private ve Name Mangling)
Tanım: İsimleri en az iki alt çizgi ile başlayan ve en fazla bir alt çizgi ile biten nitelikler ve metotlar (örn: self.
bakiye, def __hesapla(self):). Sonda da iki veya daha fazla alt çizgi varsa (init_ gibi özel metotlar) bu mekanizma uygulanmaz.
Mekanizma: İsim Karmaşası (Name Mangling): Python, bu tür isimlerle karşılaştığında, onları otomatik olarak SinifAdiuyeAdi formatına dönüştürür. Örneğin, Hesap sınıfı içindeki self.bakiye, aslında self._Hesapbakiye olarak saklanır.
Amaç: Gerçek Gizlilik DEĞİL! Name mangling’in asıl amacı, alt sınıfların farkında olmadan üst sınıftaki aynı isimli “özel” üyeleri ezmesini (override etmesini) engellemektir. Bu, özellikle büyük ve karmaşık kalıtım hiyerarşilerinde isim çakışmalarını önlemeye yardımcı olur. Tam anlamıyla bir gizlilik mekanizması olarak tasarlanmamıştır, çünkü değiştirilmiş isme hala dışarıdan erişilebilir.
Erişim: Doğrudan nesne.
ozel_nitelik şeklinde erişilemez (AttributeError verir). Ancak, değiştirilmiş isim kullanılarak (nesne._SinifAdiozel_nitelik) erişilebilir (ancak bu kesinlikle önerilmez).
class OzelOrnek:
def __init
(self, deger):
self.
cok_gizli = deger # Name mangling uygulanacak
def __gizli_metot(self): # Name mangling uygulanacak
print("Bu çok gizli (!) metot çalıştı.")
return self.
cok_gizli * 2
def public_arayuz(self):
print("Public arayüz çağrıldı.")
sonuc = self.
gizli_metot() # Sınıf içinden orijinal isimle erişilir
print(f"Gizli metodun sonucu: {sonuc}")
print(f"Gizli veriye erişim: {self.
_cok_gizli}")
ozel_nesne = OzelOrnek(50)
ozel_nesne.public_arayuz()

Dışarıdan doğrudan erişim denemeleri

try:
print(ozel_nesne.cok_gizli)
except AttributeError as e:
print(f"\nHata (Doğrudan __ Erişim): {e}") # AttributeError: 'OzelOrnek' object has no attribute '
cok_gizli'
try:
ozel_nesne._gizli_metot()
except AttributeError as e:
print(f"Hata (Doğrudan _
Metot Çağrısı): {e}")

İsim karmaşası ile erişim (ASLA YAPMAYIN!)

print("\nİsim karmaşası ile erişim (Kötü Pratik):")
print(f"Değiştirilmiş isimle veri: {ozel_nesne.OzelOrnekcok_gizli}")
ozel_nesne._OzelOrnek
_gizli_metot()
Özetle:

Public: Dış arayüz, serbest erişim.
_Protected: İç kullanım uyarısı, teknik engel yok.
__Private: İsim çakışmasını önleme mekanizması (name mangling), gerçek gizlilik değil.
Python’da gerçek anlamda veri gizlemek mümkün değildir, felsefe açıklık ve konvansiyonlara dayanır.

Bölüm 4: Kontrollü Erişim: Getters, Setters ve Property’ler
Kapsüllemenin “veri gizleme” yönünü pratikte uygulamanın ve verilere kontrollü erişim sağlamanın yolu, doğrudan nitelik erişimi yerine metotlar kullanmaktır.

4.1. Geleneksel Getter ve Setter Metotları
Diğer OOP dillerinde yaygın olan bir yaklaşımdır. Her “gizli” nitelik için bir “getter” (değeri okuyan) ve bir “setter” (değeri değiştiren) metot tanımlanır.

Getter (get_...): Nitelik değerini döndürür.
Setter (set_...): Yeni bir değer alır, genellikle bu değeri doğrular (validation) veya başka işlemler yapar ve ardından iç niteliği günceller.
class OgrenciGeleneksel:
def init(self, ad, yas):
self.ad = ad # Public
self.yas = 0 # Korumalı, yaş için kontrol ekleyeceğiz
self.set_yas(yas) # Başlangıçta setter ile atama yapmak iyi bir pratik
def get_yas(self):
"""Öğrencinin yaşını döndürür."""
print("(Getter çağrıldı)")
return self._yas
def set_yas(self, yeni_yas):
"""Öğrencinin yaşını ayarlar (doğrulama ile)."""
print("(Setter çağrıldı)")
if isinstance(yeni_yas, int) and 0 <= yeni_yas <= 120:
self._yas = yeni_yas
else:
# print("Hata: Geçersiz yaş değeri!")
raise ValueError("Yaş 0 ile 120 arasında bir tam sayı olmalıdır.")
def __str
_(self):
return f"Öğrenci(Ad: {self.ad}, Yaş: {self._yas})"
ogr1 = OgrenciGeleneksel("Deniz", 20)
print(ogr1)

Yaşı getter ile al

mevcut_yas = ogr1.get_yas()
print(f"Mevcut Yaş: {mevcut_yas}")

Yaşı setter ile değiştir

try:
ogr1.set_yas(21)
print(ogr1)
ogr1.set_yas(-5) # Hata fırlatacak
except ValueError as e:
print(f"Hata Yakalandı: {e}")

Doğrudan erişim hala mümkün ama önerilmez

print(ogr1._yas)

ogr1._yas = -10 # Doğrulama atlanmış olur!

Getter/Setter yöntemi işe yarar ancak Python’da biraz “Java-vari” veya “C++-vari” kabul edilir. Her nitelik için iki ayrı metot yazmak kodu uzatabilir ve erişim nesne.get_yas() gibi olur, nesne.yas gibi doğal görünmez.

4.2. Property’ler: Pythonic Yaklaşım (@property, @setter, @deleter)
Python, niteliklere erişimi kontrol etmenin daha zarif ve “Pythonic” bir yolunu sunar: property’ler. Property’ler, metotları sanki public niteliklermiş gibi kullanmamıza olanak tanır. Bu, sınıfın dış kullanıcısı için basit bir nitelik erişimi (nesne.nitelik) sağlarken, arka planda getter, setter ve hatta deleter metotlarının çalışmasını sağlar.

Property oluşturmak için dekoratörler kullanılır:

@property: Getter metodunu tanımlar. Bu metot, nitelik adı ile aynı isme sahip olmalı ve sadece self parametresi almalıdır. Nitelik okunduğunda (nesne.nitelik) bu metot çalışır.
@nitelik_adı.setter: Setter metodunu tanımlar. Bu metot, nitelik adı ile aynı isme sahip olmalı ve self dışında atanacak yeni değeri alan bir parametre daha almalıdır. Niteliğe bir değer atandığında (nesne.nitelik = deger) bu metot çalışır. İçinde genellikle doğrulama mantığı bulunur.
@nitelik_adı.deleter: Deleter metodunu tanımlar (daha az kullanılır). Bu metot, nitelik adı ile aynı isme sahip olmalı ve sadece self parametresi almalıdır. Nitelik silinmeye çalışıldığında (del nesne.nitelik) bu metot çalışır.
Önceki öğrenci örneğini property kullanarak yeniden yazalım:

class OgrenciProperty:
def init(self, ad, yas):
self.ad = ad # Public nitelik
# Yaşı doğrudan atamak yerine setter property'sini kullanıyoruz
self.yas = yas # Bu satır @yas.setter'ı tetikler
@property
def yas(self):
"""Yaş niteliği için getter."""
print("(Property Getter çağrıldı)")
# Genellikle gizli bir niteliğe (yas) erişir
# Ancak bu örnekte, setter'da kontrol edildiği için doğrudan __yas olabilir
# Ama konvansiyon olarak _yas kullanalım.
# Aslında, setter tanımlandığında, getter'ın bir iç değişkene
# referans vermesi zorunlu değildir, sadece değeri döndürmesi yeterli
# gibi görünse de, değeri bir yerde saklamamız gerekir.
# Bu yüzden genellikle bir _yas veya __yas kullanılır.
# Kafa karışıklığını önlemek için __yas kullanalım (name mangling ile).
return self.
yas
@yas.setter
def yas(self, yeni_yas):
"""Yaş niteliği için setter (doğrulama ile)."""
print("(Property Setter çağrıldı)")
if isinstance(yeni_yas, int) and 0 <= yeni_yas <= 120:
# Değeri gizli bir nitelikte sakla
self.
yas = yeni_yas # Name mangling uygulanacak (_OgrenciPropertyyas)
else:
raise ValueError("Yaş 0 ile 120 arasında bir tam sayı olmalıdır.")
# Deleter (isteğe bağlı)
@yas.deleter
def yas(self):
print("(Property Deleter çağrıldı)")
print("Yaş niteliği silinemez.")
# veya del self.
yas ile gerçekten silinebilir
# raise AttributeError("Yaş niteliği silinemez.")
def __str
_(self):
# Getter property'sini kullanarak yaşı alıyoruz
return f"Öğrenci(Ad: {self.ad}, Yaş: {self.yas})"

Kullanım

ogr2 = OgrenciProperty("Efe", 25) # init -> self.yas = 25 -> @yas.setter çağrılır
print(ogr2)

Nitelik gibi erişim (arka planda @property getter çalışır)

print(f"Öğrencinin yaşı: {ogr2.yas}")

Nitelik gibi atama (arka planda @yas.setter çalışır)

try:
ogr2.yas = 30
print(ogr2)
ogr2.yas = -10 # ValueError fırlatır
except ValueError as e:
print(f"Hata Yakalandı: {e}")

Silme denemesi (arka planda @yas.deleter çalışır)

try:
del ogr2.yas
except AttributeError as e:
print(f"Silme Hatası: {e}")

Dikkat: __yas'a name mangling ile hala erişilebilir ama KULLANILMAMALI

print(ogr2.OgrenciProperty_yas)

Property’ler, sınıfın dış kullanıcısı için basit bir arayüz sunarken (nesne.yas), sınıfın yazarı için erişimi kontrol etme, doğrulama ekleme ve iç implementasyonu gizleme imkanı tanır. Bu, Python'da kapsüllemeyi uygulamanın en temiz ve tercih edilen yoludur.

Bölüm 9: Sonuç: Kapsüllemenin Önemi
Kapsülleme, Nesne Yönelimli Programlamanın sadece bir teorik prensibi değil, aynı zamanda pratik yazılım mühendisliğinin temel bir taşıdır. Verileri ve davranışları mantıksal birimlerde birleştirerek ve iç detayları gizleyerek kodun daha sağlam, esnek, sürdürülebilir ve anlaşılır olmasına yardımcı olur.

Python, diğer diller gibi katı erişim belirleyicileri sunmasa da, _protected ve __private (name mangling) gibi konvansiyonlarla ve özellikle @property dekoratörü ile kapsülleme prensiplerini etkin bir şekilde uygulamamıza olanak tanır. Bu mekanizmalar, nesnenin iç durumunun bütünlüğünü korumamızı, kontrollü erişim sağlamamızı ve en önemlisi, sınıfın iç yapısını değiştirdiğimizde bile dış kodu bozmadan geliştirmeye devam edebilmemizi sağlar.

İyi kapsüllenmiş sınıflar yazmak, sadece o anki problemi çözmekle kalmaz, aynı zamanda gelecekteki değişikliklere ve genişlemelere karşı daha dayanıklı, daha kolay test edilebilir ve takım çalışmasına daha uygun kodlar üretmemizi sağlar. Bu nedenle, Python’da OOP ile çalışırken kapsülleme prensiplerini anlamak ve uygulamak, kaliteli yazılım geliştirmenin ayrılmaz bir parçasıdır.

Abdulkadir Güngör - Kişisel WebSite
Abdulkadir Güngör - Kişisel WebSite
Abdulkadir Güngör - Özgeçmiş
Github
Github
Linkedin