ProgramlamaBackend Geliştirici

Python'da diziler (Sequence) arayüzü nasıl gerçekleştirilir? Özel yöntemler __getitem__, __len__ neden uygulanmalıdır ve hangi gizli tehlikeler vardır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Konunun Tarihi:

Diziler, Python'da en eski ve en temel kavramlardan biridir. Klasik örnekler — listeler (list), dizgeler (str), demetler (tuple). Dizilerle etkileşim için özel bir protokol ayrılmıştır: __getitem__ ve __len__ yöntemlerini uygulamak gerekir. Bu, nesnenin "dizi gibi" davranmasını sağlar — indeksleme, dilimler (slice) destekler, döngülerde çalışır ve hatta bazı standart fonksiyonlar ile uyumlu hale gelir.

Sorun:

Bu yöntemlerin doğru bir şekilde uygulanmaması durumunda, kullanıcı tanımlı sınıf indeksleme işlemleri, for döngüsü, len() gibi fonksiyonlarla çalışamaz. Genellikle başlangıç seviyesindeki geliştiriciler sadece bir yöntemi uygulayarak, istisna işleme ile ilgilenmeden, dilim (slice) desteğini sağlamadan çalışmaya başlarlar ve beklenmeyen ya da hatalı davranışlar alırlar.

Çözüm:

İndekslemeyi ve dilimleri desteklemek için __getitem__(self, key) yöntemini ve len() ile doğru itilebilirlik için __len__(self) yöntemini uygulamak gerekir. Dilim desteği için, __getitem__ içinde key tipini ayırt etmek ve dilim (slice) nesnelerini doğru bir şekilde işlemek gereklidir.

Kod Örneği:

def is_even(n): return n % 2 == 0 class EvenSequence: def __init__(self, size): self.size = size def __getitem__(self, index): if isinstance(index, slice): return [x for x in range(self.size)[index] if is_even(x)] if index < 0 or index >= self.size: raise IndexError('Index out of bounds') return index if is_even(index) else None def __len__(self): return self.size

Ana Özellikler:

  • Her iki yöntem de uygulanırsa, Python’un çoğu fonksiyonu ve sözdizimi ile etkileşim.
  • Dilim (slice) desteği için __getitem__ içinde dilim nesnelerini işlemek gereklidir.
  • __len__ uygulamadan, nesne len() ile çalışmaz ve bazı standart fonksiyonların tam listesinde işlev görmez.

Sürpriz Sorular.

Nesnenin dizi gibi çalışması için yalnızca getitem yöntemi ile sınırlandırılabilir mi?

Kısmen. Sadece __getitem__ uygulandığında, nesne üzerinde for döngüsü ile iterasyon yapabilir ve elemanları indeksleyebilirsiniz, ancak len() çalışmaz.

Kod Örneği:

class SeqOnlyGetitem: def __getitem__(self, index): if index >= 10: raise IndexError return index * 2 s = SeqOnlyGetitem() for x in s: print(x) # Çalışır (iterasyon) # print(len(s)) # TypeError Hatası

Negatif indeksler nasıl işlenmeli ve eğer dikkate alınmazsa ne olur?

Negatif indeksler, Python'da dizilerin temel bir özelliğidir. Eğer işlenmezse, nesne kullanıcı için beklenmedik bir şekilde davranır.

class NegIndex: def __init__(self, data): self.data = data def __getitem__(self, index): if index < 0: index += len(self.data) return self.data[index]

Kendi Sequence sınıfınız için contains veya iter uygulamak gerekli midir?

Zorunlu değildir. Eğer __getitem__ ve __len__ uygulanmışsa, in kullanımı çalışır ve for bu yöntemleri iterasyon için kullanır. Bu yöntemleri doğrudan uygulamak genellikle gereksizdir, ancak performansı artırabilir.

Yaygın Hatalar ve Antipatternler

  • İndeks aralıklarını kontrol etmemek, bu da IndexError veya beklenmeyen sonuçlar ile sonuçlanır.
  • Dilim (slice) desteğini sağlamamak, bu nedenle obj[2:10:2] hataya neden olur.
  • Negatif indeksleri unutur (obj[-1]).

Gerçek Hayattan Örnek

Negatif Durum

Geliştirici sınıfı için yalnızca pozitif indeksler için getitem'i uyguladı. Modül bazı unit testlerinden geçti, ancak gerçek kullanımda mevcut olmayan bir indeks veya negatif bir indeks alındığında her şey bozuldu.

Artılar:

  • Hızlı bir başlangıç uygulaması.

Eksiler:

  • Gerçek hayatta beklenmedik hatalar.
  • Kullanımda zorluk (negatif indeksi ile son elemanları alamama, dilim çalışmama, len() çalışmama).

Pozitif Durum

Ekip her iki yöntemi (getitem ve len) uyguladı, dilim, negatif indeksleri dikkate aldı, doğru istisnalar atılmasını sağladı. Nihai sınıf Python’un tüm standart durumlarında çalıştı.

Artılar:

  • Python'un API'si açısından öngörülebilir davranış.
  • Kullanım kolaylığı, minimum hata.

Eksiler:

  • Biraz daha fazla kod, tasarımda ayrıntılara dikkat gerektirir.