Python'daki in operatörü, bir öğenin koleksiyonda olup olmadığını belirler. Kullanıcı nesneleri için, x in your_obj yapısının desteklenmesi için contains metodunu uygulamak gerekir. Eğer bu yoksa, yorumlayıcı __iter__ veya __getitem__ yöntemiyle nesneyi yinelemeye çalışacaktır, ancak davranış ve verimlilik değişiklik gösterebilir.
Örnek:
class MyBag: def __init__(self, items): self.items = items def __contains__(self, value): return value in self.items bag = MyBag([1,2,3]) print(2 in bag) # True print(5 in bag) # False
Eğer sadece __iter__ (veya sadece __getitem__) uygulanırsa, in çalışacaktır ama daha az verimli ve bazen beklenildiği gibi değil.
Dikkat Edin: Eğer koleksiyon devasa ise ve kontrol naif bir şekilde uygulanmışsa (örneğin, tüm listeyi döngü ile kontrol etmek), performans sorunları yaşanabilir. Hızlı kontroller için, örneğin, kümeler kullanılır.
Doğru çalışması için sadece
__iter__veya sadece__getitem__uygulamak yeterli mi? Davranış nasıl değişir?
Cevap:
__contains__ yoksa, Python öğeleri yinelemek için __iter__ (varsa) veya __getitem__ (0 indeksinden başlayarak, IndexError hatası fırlatana kadar) kullanmaya çalışacaktır.Örnek:
class Weird: def __getitem__(self, idx): if idx < 3: return idx raise IndexError w = Weird() print(2 in w) # True print(5 in w) # False
Hikaye
Bir projede, varlıkları saklamak için kullanıcıdan oluşan bir konteyner yalnızca
__iter__yöntemini yeniden yazdı,__contains__'u uygulamayı unuttu.inoperatörü yalnızca yavaş çalışmakla kalmadı (büyük koleksiyonlar için gecikmeler belirgindi), aynı zamanda iteratör yanlışlıkla StopIteration türünde olmayan hatalar fırlattığında gizemli hatalarla aniden çökmesine neden oldu.
Hikaye
Elemanların "anlık" olarak indekse göre hesaplandığı bir sınıf için geliştirici yalnızca
__getitem__'i uyguladı. Büyük bir x ilex in objkontrolü yapıldığında uzun döngüler ve hatta bellek dışı (Out Of Memory) hataları ile karşılaşıldı - çünküinsıfırdan başlayarak tüm indeksleri kontrol eder ve bir IndexError ile karşılaşana kadar devam eder.
Hikaye
Bir projede,
iniçin yalnızca__iter__'e dayanan özel bir sözlük uygulandı. Bu, 100.000 anahtar için aramanın standart dict'deki (burada__contains__verimli bir şekilde uygulanmıştır) milisaniyeler yerine saniyeler sürmesine neden oldu.