Python öznitelikleri: nasıl çalıştıklarını anlıyoruz 🐍

Öznitelikler, Python nesne modelinin temelidir, ancak çoğu acemi (ve hatta birçok orta seviye) bunları sezgisel olarak kullanır, "kaputun altında" neler olduğunu anlamaz. Sonuç: öngörülemeyen kod davranışı, bellek tüketimi ve spagetti API.

Gelin ayrıntılara bakalım 👇

1️⃣ Arama sırası (MRO)
Python şu prensiple yaşar: önce nesne, sonra sınıf.

obj.attr'ye eriştiğinizde, yorumlayıcı önce obj.__dict__'ye bakar. Bulamazsa Class.__dict__'ye gider.
Yanlışlıkla obj.attr'ye bir şey yazarsanız, sınıf özniteliğini gizleyen bir örnek özniteliği oluşturursunuz.

class Hero:
weapon = "Sword"

h = Hero()
h.weapon = "Gun" # Artık h'nin kendi silahı var, sınıf hala kılıçla

Bu bir hata değil, bir özellik, ancak bunu kontrol edin. Herkes için özniteliği değiştirmek istiyorsanız sınıfa başvurun.

2️⃣ __dict__ vs __slots__
Varsayılan olarak her nesnenin __dict__'si vardır — özniteliklerin saklandığı bir karma tablo (sözlük). Bu esnektir, ancak bellek açısından pahalıdır.

Aynı türden milyonlarca nesne oluşturuyorsanız __slots__ kullanın.
🔵Ne sağlar: Örnek için __dict__ oluşturulmasını engeller, öznitelik kümesini bellekte sabitler (dizi gibi).
🔵Kazanç: %25-30 daha az bellek tüketimi ve biraz daha hızlı erişim.
🔵Bedel: Anında yeni öznitelik ekleme dinamik yeteneğini kaybedersiniz.

3️⃣ Kapsülleme yanılsaması
Python'da "private" alanlar yoktur. Hiç yok.
__attribute şeklindeki yapılar veri koruması değil, name mangling (ad bozma)'dir. Python, değişkeni _ClassName__attribute olarak yeniden adlandırır, böylece alt sınıflarda yanlışlıkla üzerine yazılmaz.
Verilerinize kimsenin erişemeyeceğini umarak __ yazarsanız, dir() kullanmayı bilen herkes her şeyi görür. _private (tek alt çizgi) yazarsanız — "dokunma, bu iç API" anlamına gelir. Bu bir kültür meselesidir, derleyici değil.

Verileri gizlemek mi istiyorsunuz? Tek alt çizgi _'yi yalnızca iş arkadaşlarınıza sinyal olarak kullanın: "Buna dokunma, bu iç işler".

4️⃣ @property: etik getter
Python'da asla Java tarzı getter'lar (get_value(), set_value()) yapmayın. Bir özniteliğe erişirken mantık gerekiyorsa @property kullanın.
@property, bir metodu özniteliğe dönüştürmenizi sağlar. Temiz bir API (nokta ile erişim) korursunuz, ancak kaputun altında verileri doğrulayabilir, erişimi günlüğe kaydedebilir veya değerleri anında hesaplayabilirsiniz.
class DataStorage:
def __init__(self, value):
self._value = value

@property
def value(self):
return self._value

@value.setter
def value(self, new_val):
if not isinstance(new_val, int):
raise ValueError("Sadece int, bebek" )
self._value = new_val


Böylece temiz bir arayüz korursunuz: obj.value = 10, normal bir alanla çalışmak kadar basit görünür, ancak ne yazıldığını kontrol edersiniz.

Python'da sizi düşündüren başka hangi "sihirli" yerler var? Yorumlara yazın, inceleyelim. 👇

#anaatomisi_piton