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:
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
Yalnızca iter tanımlanmış özel bir yapı uygulandı, dilimleme ve indeksleme kullanılabilir olduğunu düşünerek.
Artılar:
Eksiler:
Sınıf, dilimleme ve int indeksleri ile çalışma desteği ile getitem'i ve len'i uyguluyor.
Artılar:
Eksiler: