Gizli Öznitelikler
Coddy'nin Python Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 15 / 64.
Özel öznitelikler, belirli verilere sınıf dışından doğrudan erişilmemesi gerektiğini belirtmek için alt çizgiler kullanır.
Neden özel özniteliklere ihtiyacımız var? Bir banka hesabınız olduğunu hayal edin. Kimsenin bakiyenizi doğrudan değiştirmesini istemezsiniz; bankanın işlemi doğrulayabilmesi, dolandırıcılık kontrolü yapabilmesi, kayıt tutabilmesi vb. için uygun kanallardan (para yatırma/çekme metotları) geçmeleri gerekir. Özel öznitelikler de aynı şekilde çalışır; verilerinizin yanlış bir şekilde değiştirilmesini önlerler.
İşte tek alt çizgi ("dahili kullanım" geleneği) kullanan bir örnek:
class Person:
def __init__(self, name, age):
self._name = name # "korumalı" - dahili kullanım
self._age = age # "korumalı" - dahili kullanımTek alt çizgili özniteliklere hala erişilebilir, ancak bu erişilmemesi gerektiğine dair bir işarettir:
person = Person("Alice", 30)
print(person._name) # Çalışır, ancak önerilmezDaha güçlü gizlilik (ad karıştırma - name mangling) için çift alt çizgi kullanın:
class Person:
def __init__(self, name, age):
self.__name = name # "private" - ad karıştırmaya (name mangling) uğrar
self.__age = age # "private" - ad karıştırmaya (name mangling) uğrar
def get_name(self):
return self.__name
def set_age(self, age):
if age >= 0:
self.__age = age
else:
print("Age must be positive!")Neden getter ve setter metotları kullanılır? Bunlar kapı bekçileri gibidir. Herhangi birinin __age değerini doğrudan değiştirmesine izin vermek yerine (ki bu negatif yaşlara veya diğer geçersiz verilere neden olabilir), onları önce girişi doğrulayan set_age() metodunu kullanmaya zorlarız. Bu, hataları önler ve veri bütünlüğünü sağlar.
"Ekstra kodun" bir amacı vardır:
get_name()- İsmi okumak için kontrollü erişimset_age(age)- Değişikliklere izin vermeden önce yaşı doğrular (negatif yaş yok!)- Bu metotlar olmadan, birisi
age = -100olarak ayarlayabilir ve programınızı bozabilir
Özel (private) özniteliklerle etkileşim kurmak için erişimci (accessor) yöntemlerini kullanın:
person = Person("Bob", 25)
print(person.get_name()) # Bob
person.set_age(30) # Geçerli: yaş 30 olur
person.set_age(-5) # Geçersiz: Yaş pozitif olmalıdır! (yaş 30 kalır)Avantajı görüyor musunuz? set_age() yöntemi geçersiz verileri engeller. O olmasaydı, yanlışlıkla yaşı -5 olan bir kişi oluşturabilirdiniz, ki bu hiç mantıklı değil!
Çift alt çizgi öznitelikleri "ad karıştırma" (name mangling) işlemine uğrar ancak yine de bunlara erişilebilir:
person = Person("Charlie", 35)
# Bu çalışmaz:
# print(person.__name) # AttributeError
# Ancak bu çalışır (önerilmez):
print(person._Person__name) # CharlieGerçek dünya örneği - Neden tüm bu kodlar?
class BankAccount:
def __init__(self, balance):
self.__balance = balance # Gizli: doğrudan değiştirilemez
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return True
return False
def get_balance(self):
return self.__balance
# Gizli öznitelikler olmadan:
# account.__balance = -1000000 # Felaket! Negatif bakiyeye izin verildi
# Gizli özniteliklerle:
account = BankAccount(100)
account.deposit(50) # Güvenli: doğrulandı
print(account.get_balance()) # 150"Ekstra kod" (metotlar) verilerinizi geçersiz değişikliklerden korur. Bu, değerli eşyalarınızı korumasız bırakmak yerine güvenlik görevlilerine sahip olmak gibidir.
Çıktı:
Alice
Bob
Age must be positive!
Charlie
150Tek alt çizgi _attribute geleneksel olarak "yalnızca dahili kullanım" anlamına gelir. Çift alt çizgi __attribute daha güçlü gizlilik için ad karıştırmayı (name mangling) tetikler. Özel verilerle düzgün bir şekilde etkileşime girmek ve doğrulama eklemek için getter/setter metotlarını (erişimci metotlar) kullanın. "Ekstra kod", verilerin her zaman geçerli olmasını sağlayarak hataları önler.
Görev
Kolayuser.py dosyasındaki User sınıfını özel parola işlevselliği ile tamamlayın, ardından bunu driver.py dosyasında kullanın. Parola kontrol etme ve değiştirme metotlarını uygulamak için TODO yorumlarını takip edin.
Kopya kağıdı
Özel (private) öznitelikler, verilere sınıf dışından doğrudan erişilmemesi gerektiğini belirtmek için alt çizgi kullanır.
Tek alt çizgi (_attribute) - "dahili kullanım" için bir kuraldır:
class Person:
def __init__(self, name, age):
self._name = name # "protected" - dahili kullanım
self._age = age # "protected" - dahili kullanımÇift alt çizgi (__attribute) - daha güçlü gizlilik için isim karıştırmayı (name mangling) tetikler:
class Person:
def __init__(self, name, age):
self.__name = name # "private" - isim karıştırmaya uğrar
self.__age = age # "private" - isim karıştırmaya uğrar
def get_name(self):
return self.__name
def set_age(self, age):
if age >= 0:
self.__age = age
else:
print("Age must be positive!")Özel özniteliklerle etkileşim kurmak için erişimci (accessor) yöntemlerini kullanın:
person = Person("Bob", 25)
print(person.get_name()) # Bob
person.set_age(30)
person.set_age(-5) # Age must be positive!Çift alt çizgili öznitelikler isim karıştırmaya uğrar ancak yine de erişilebilirler (önerilmez):
# Bu çalışmaz:
# print(person.__name) # AttributeError
# Ancak bu çalışır (önerilmez):
print(person._Person__name) # CharlieKendin dene
# YAPILACAK: user modülünden User sınıfını içe aktarın
# YAPILACAK: Girdiden test durumunu alın
test_case = input()
if test_case == "constructor_test":
# YAPILACAK: "secure123" başlangıç şifresiyle bir User nesnesi oluşturun
user = User("secure123")
print("User created successfully")
print("Initial password set")
elif test_case == "correct_password_test":
# YAPILACAK: "secure123" başlangıç şifresiyle bir User nesnesi oluşturun
user = User("secure123")
# YAPILACAK: check_password metodunu doğru şifre ile test edin
# Eğer True dönerse "Password check successful!" yazdırın
# Eğer False dönerse "Password check failed!" yazdırın
result = user.check_password("secure123")
if result:
print("Password check successful!")
else:
print("Password check failed!")
elif test_case == "incorrect_password_test":
# YAPILACAK: "secure123" başlangıç şifresiyle bir User nesnesi oluşturun
user = User("secure123")
# YAPILACAK: check_password metodunu yanlış şifre "wrong" ile test edin
# Eğer False dönerse "Incorrect password rejected!" yazdırın
# Eğer True dönerse "Security issue: incorrect password accepted!" yazdırın
result = user.check_password("wrong")
if not result:
print("Incorrect password rejected!")
else:
print("Security issue: incorrect password accepted!")
elif test_case == "change_password_test":
# YAPILACAK: "secure123" başlangıç şifresiyle bir User nesnesi oluşturun
user = User("secure123")
# YAPILACAK: Şifreyi "secure123"ten "newpass456"ya değiştirmeyi test edin
# Eğer True dönerse "Password changed successfully!" yazdırın
# Eğer False dönerse "Password change failed!" yazdırın
result = user.change_password("secure123", "newpass456")
if result:
print("Password changed successfully!")
else:
print("Password change failed!")
# YAPILACAK: "newpass456" şifresini kontrol ederek yeni şifrenin çalıştığını doğrulayın
# Eğer True dönerse "New password works!" yazdırın
# Eğer False dönerse "New password doesn't work!" yazdırın
if user.check_password("newpass456"):
print("New password works!")
else:
print("New password doesn't work!")
elif test_case == "change_password_wrong_old_test":
# YAPILACAK: "secure123" başlangıç şifresiyle bir User nesnesi oluşturun
user = User("secure123")
# YAPILACAK: Yanlış eski şifre ile şifre değiştirmeyi deneyin
# Eğer False dönerse "Security working: incorrect old password rejected!" yazdırın
# Eğer True dönerse "Security issue: password changed with wrong old password!" yazdırın
result = user.change_password("wrong", "hackerpw")
if not result:
print("Security working: incorrect old password rejected!")
else:
print("Security issue: password changed with wrong old password!")
elif test_case == "comprehensive_test":
# YAPILACAK: "secure123" başlangıç şifresiyle bir User nesnesi oluşturun
user = User("secure123")
print("User created with initial password")
# YAPILACAK: check_password metodunu doğru şifre ile test edin
if user.check_password("secure123"):
print("Initial password verification successful")
# YAPILACAK: check_password metodunu yanlış şifre ile test edin
if not user.check_password("wrongpass"):
print("Incorrect password properly rejected")
# YAPILACAK: Şifreyi "secure123"ten "newpass456"ya değiştirmeyi test edin
if user.change_password("secure123", "newpass456"):
print("Password successfully changed")
# YAPILACAK: Eski şifrenin artık çalışmadığını doğrulayın
if not user.check_password("secure123"):
print("Old password no longer works")
# YAPILACAK: Yeni şifrenin çalıştığını doğrulayın
if user.check_password("newpass456"):
print("New password works correctly")
# YAPILACAK: Yanlış eski şifre ile şifre değiştirmeyi deneyin
if not user.change_password("wrongold", "hackerpw"):
print("Security maintained: wrong old password rejected")
# YAPILACAK: Başarısız değiştirme denemesinden sonra şifrenin hala güvenli olduğunu doğrulayın
if user.check_password("newpass456"):
print("Password remains secure after failed change attempt")
else:
print("Unknown test case")Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Object Oriented Programming bölümündeki tüm dersler
1OOP Temelleri
Harici DosyalarOOP'ye GirişSınıflar ve Nesnelerself ParametresiMetotlarÖzniteliklerYapıcı Metot (__init__)Özet - Basit Hesap Makinesi4Kalıtım
Temel Kalıtımsuper() FonksiyonuMetot Geçersiz KılmaÇoklu KalıtımMetot Çözümleme SırasıÖzet - Çalışan Hiyerarşisi7Özel Metotlar
Sihirli Metotlara GirişOperatör Aşırı YüklemeKapsayıcı Sihirli MetotlarıÖzet - Özel Liste10Tasarım Kalıpları Bölüm 1
Tasarım kalıplarına girişSingleton KalıbıFactory KalıbıObserver KalıbıStrategy Kalıbı13Final Meydan Okumaları
E-öğrenme PlatformuBankacılık SistemiOyun Karakteri GeliştirmeAraç Kiralama Servisi5Çok Biçimlilik (Polymorphism)
Metot Geçersiz Kılmaya Yeniden BakışDuck TypingSoyut Sınıflar ve MetotlarArayüz TasarımıÖzet - Şekil Hesaplayıcı8İleri Düzey OOP Kavramları
Kompozisyon ve KalıtımMixinsStatik ve Sınıf MetotlarıSınıf DekoratörleriBağlam Yöneticileri11Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit Kalıbı