Pythton’da “in” ifadesi birden fazla amaçla kullanılabilir. Örneğin aşağıdaki kod parçasında bir öğenin liste içerisinde olup olmadığını kontrol edebiliriz:
some_list = [1, 2, 3, 4, 5]
print(2 in some_list)
Bir sonraki örnekte ise i
değerlerinin sırasıyla liste içerisindeki öğelere eşit olacağını biliyoruz:
for i in [1, 2, 3, 4, 5]:
print(i)
Peki bu iki örnekteki in ifadesi aynı operatöre mi karşılık geliyor? in ifadesine biraz daha detaylı bakarak inceleyelim.
Yukarıdaki örneklerde kullanılan operatörler aynı konsepte sahipler. Ancak aynı operatör değiller.
print(2 in some_list)
örneğindeki in
operatörü birden fazla farklı durum için kullanılır. Python dökümanlarına göre: x in y
ifadesi y.__contains__(x)
metodunu çalıştırır – eğer y
, __contains__
metoduna sahipse.
y, bu metoda sahip değilse, x in y
ifadesi bir iterasyon oluşturmaya çalışır. Bu durumda x
‘in değerini ya y.__iter__()
ile elde etmeye çalışır, ya da, __iter__
tanımlı değilse y.__getitem__(x)
ile elde etmeyi dener.
Bir for
döngüsü içerisinde in
sadece döngü-indexine değer atamak için işaretleyici görevi görür. Yine Python dökümanlarına göre: for döngüsü içerisindeki in
‘den sonra gelen ifade bir iteratör vermek için kullanılır. Döngü bloğu böylece iteratör içerisindeki her öğe için çalışır. for
ifadesi __contains__
veya __getitem__
ile ilgilenmez.
Örneğin aşağıdaki gibi bir sınıfımız olsun:
>>> class C:
... def __iter__(self):
... return iter([1,2,3,4])
>>>
C sınıfı __contains__ metodunu implement etmediği için buradaki in ifadesi bir iteratör döndürür:
>>> c = C()
>>> 2 in c
True
>>> 5 in c
False
Kısaca söylersek. in
ifadesinin iki tür kullanımı bulunur:
- bir yapının içinde değerin olup olmadığını test eder (
__contains__
ile) - bir diziyi döngüye sokar (
Iterable
ile)
in ifadesi hangi arama yöntemini kullanır
in
operatorü ile bir dizi içerisindeki değeri kontrol ettiğimizde __contains__
fonksiyonunun çağırılacağını söyledik. Ancak bu fonksiyon farklı türler için farklı şekilde implement edilir.
str
, list
ve tuple
için __contains__ bir linear search (O(N)
) çalıştırır. C ile implement edildiği için de normalde python ile yazacağımız linear search ifadesine göre muhtemelen daha hızlıdır.
set
ve dict
için ise bir hash-table lookup çalıştırır ki bu daha da hızlıdır. Ortalama olarak O(1)
zaman karmaşıklığına sahiptir.
Haliyle farklı türler için farklı performans özellikleri gösterecektir.
Birden fazla in ifadesi kullanımı
Peki birden fazla in ifadesi kullandığımızda ne oluyor? Örneğin aşağıdaki ifadeden ne anlamamız gerekir:
"a" in "bar" in "foo" in "baz"
Python soldan sağa doğru çalışır. Bu şekilde akışı parantezler ile kontrol edebiliriz. Yukarıdaki ifade de doğal olarak şöyle düşünülebilir:
"a" in "bar" and "bar" in "foo" and "foo" in "baz"
Ve sonuç olarak False
döner.
Daha açık yazarsak;
("a" in "bar") and ("bar" in "foo") and ("foo" in "baz")
– ya da False
iki boyutlu array için in ifadesi
Aşağıdaki gibi iki boyutlu bir listemiz olsun:
x = ["Hello", "World"]
y = ["Hi", "Guys"]
z = [x, y]
z listesi, x ve y listelerini içeriyor. Peki “Hello” öğesini z içerisinde ararsak ne dönmesi gerekir:
"Hello" in z
Bu kodu çalıştırırsanız, beklentinizin aksine, False döndüğünü göreceksiniz. Peki neden?
in ifadesinin burada beklediğimiz sonucu vermesi için bir döngü kullanmamız gerekir. Çünkü "Hello"
gerçekten de z
‘nin içinde bulunmaz — "Hello"
x
‘in içerisindedir, o da z
‘nin içinde:
>>> x = ["Hello", "World"]
>>> y = ["Hi", "Guys"]
>>> z = [x, y]
>>> "Hello" in x
True
>>> x in z
True
>>> any("Hello" in a for a in z)
True
Yukarıdaki kod parçasında a
, x
ve y
üzerinde döner. Eğer herhangi (any
) bir öğe için Yukarıdaki kod parçasında a
, x
ve y
üzerinde döner. Eğer herhangi (any
) bir öğe için "Hello" in a
ifadesi sağlanırsa True döner.
Bunu yapmanın başka bir yolu da aşağıdaki kullanım olabilir:
>>> [b for a in z for b in a]
['Hello', 'World', 'Hi', 'Guys']
>>> "Hello" in (b for a in z for b in a)
True
Önceki kullanımda olduğu gibi, a
, z
‘nin içindeki tüm listeler üzerinde döner. Ancak bu döngü içerisinde bir de b
ile döngü kurarız. Aynı şekilde, "Hello" in
(iterable) ifadesi sağlanırsa True sonucunu alırız.