ProgramlamaBackend geliştirici

Python'daki 'Sequence' protokolünü açıklayın, nasıl uygulandığını ve bunun sıradan yinelemeli nesnelerden farkının ne olduğunu anlatın.

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

Cevap.

Python'da 'Sequence' protokolü, liste veya demet gibi dizinlenebilir ve yinelemeli nesneler için bir arayüz belirler. Tarihsel olarak, diziler, verileri yapılandırma doğal işlemlerini desteklemek için Python'un ilk sürümlerinde ortaya çıktı: dizinleme, dilimleme, elemanları yineleme.

Sorun — kullanıcı tanımlı bir sınıfın bir dizi gibi davranması için sadece iter ve next yöntemleri yeterli değildir. Dizi davranışını tam olarak desteklemek için ek yöntemlere ihtiyaç vardır.

Çözüm — kendi dizi türünüzü uygulamak için getitem yöntemini (dizinleme ve dilimler için gerekli) ve isteğe bağlı olarak len yöntemini (len() ve uzunluk kontrolü için) tanımlamanız gerekir. Böylece nesne, yinelemeyi, indeksleme erişimini, dilimleme işlemlerini ve dizilerle ilgili birçok standart Python işlemini destekleyecektir.

Kod örneği:

class MyCounter: def __init__(self, stop): self._stop = stop def __getitem__(self, index): if 0 <= index < self._stop: return index * 10 else: raise IndexError('Range dışı') def __len__(self): return self._stop c = MyCounter(5) print(c[3]) # 30 print(len(c)) # 5 for x in c: print(x)

Anahtar özellikler:

  • Nesne, getitem üzerinden dizin erişimini ve dilimlemeyi destekler.
  • len() fonksiyonunun desteklenmesi için len gereklidir.
  • Yineleme, iter tanımlanmamışsa getitem üzerinden inşa edilir.

Kandırmaca sorular.

Sadece iter ve next'i uygularsam, nesnem bir dizi (Sequence) olur mu?

Hayır. Böyle bir nesne yalnızca yinelemeli (iterable) olacak, ama dizi olmayacak. Dizinleme, dilimleme, liste benzeri nesnelerle standart işlevleri desteklemeyecek.

For döngüsünün desteklenmesi için getitem'i uygulamak zorunlu mu?

Zorunlu değil. iter tanımlanırsa, for çalışır. Ancak iter yoksa, yorumlayıcı, getitem'i 0 indeksinden başlayarak kullanmaya çalışacaktır, bu da IndexError ile sonuçlanır. Bu nedenle diziler için yeterli olan getitem'dir.

Sadece int için getitem uygulamak, fakat slice için uygular mı?

Teknik olarak, c[0] için çalışır, ancak c[1:4] dilimini almak denendiğinde başarısız olur. Dilimleri desteklemek için getitem'in slice türündeki nesneleri işleyebilmesi gerekir (slice.indices ve isinstance(key, slice) öğelerine bakınız).

Kod örneği:

class S: def __getitem__(self, idx): if isinstance(idx, slice): return [x for x in range(idx.start or 0, idx.stop or 10, idx.step or 1)] return idx * 2

Tipik hatalar ve anti-paterni

  • Sadece iter tanımlayıp, nesnenin tam bir dizi olmasını bekliyorlar.
  • getitem'i uygulayıp, ancak slice nesnelerini işlemiyorlar.
  • len'i uygulamaktan kaçınıyorlar, dolayısıyla len(obj) TypeError'a neden oluyor.

Gerçek hayat örneği

Olumsuz durum

Yalnızca iter tanımlanmış özel bir yapı uygulandı, dilimleme ve indeksleme kullanılabilir olduğunu düşünerek.

Artılar:

  • For döngüsünde çalışıyor ve jeneratörleri destekliyor.

Eksiler:

  • obj[5] veya obj[1:3] söz dizimi desteklenmiyor, hata veriyor.
  • len(obj) de çalışmıyor.

Olumlu durum

Sınıf, dilimleme ve int indeksleri ile çalışma desteği ile getitem'i ve len'i uyguluyor.

Artılar:

  • Tüm dizi işlemlerini destekliyor: dilimleme, dizinleme, len, yineleme.
  • Standart kütüphane ile entegrasyon (örneğin, random.choice).

Eksiler:

  • Dilim işleme konusunda dikkatlice uygulamaları gerekiyor, aksi takdirde dilimlerle çalışırken hatalar olabilir.