Python, ilk sürümlerinden bu yana nesneleri birbirleriyle karşılaştırmaya izin vermektedir. Nesnelerinizin "büyüklüğünü" veya "eşitliğini" tanımlamak için özel karşılaştırma yöntemleri (eq, ne, lt, le, gt, ge) oluşturulmuştur. PEP 207'nin (Python 2.1+) ortaya çıkmasıyla birlikte, programcıların karşılaştırmalardaki davranışları açıkça kontrol edebilmeleri için tek bir karşılaştırma protokolü uygulanmıştır.
Standart türler (int, str) "değer" üzerinden karşılaştırılırken, kullanıcı tanımlı sınıflar varsayılan olarak "kimlik" (is) üzerinden karşılaştırılır. Karşılaştırma sihirli yöntemlerini ya uygulamazsanız ya da yanlış uygularsanız, nesnelerinizin karşılaştırması, koleksiyonlar, sıralama, set ve dict kullanımı ile beklenmedik sonuçlar doğurabilir ve bazen tip hatalarına yol açabilir.
Sınıfınızdaki karşılaştırma yöntemlerini açıkça tanımlamanız gerekmektedir. En sık uygulanan yöntemler eq (eşitlik) ve lt (küçüktür) olup, diğer yöntemler functools.total_ordering dekoratörü yardımıyla otomatik olarak elde edilebilir.
Kod örneği:
from functools import total_ordering @total_ordering class Point: def __init__(self, x, y): self.x = x self.y = y def __eq__(self, other): if not isinstance(other, Point): return NotImplemented return self.x == other.x and self.y == other.y def __lt__(self, other): if not isinstance(other, Point): return NotImplemented return (self.x, self.y) < (other.x, other.y) # Kullanım: p1 = Point(1, 2) p2 = Point(1, 3) print(p1 < p2) # True print(p1 == p2) # False
Anahtar özellikler:
Sadece bir karşılaştırma yöntemi (eq veya lt) uygulamak mümkün mü, her şey çalışır mı?
Hayır. Sadece eq uygularsanız, eşitlik açısından doğru karşılaştırma sağlarsınız, ancak <, >, <=, >= operatörleri standart davranış sergiler (genellikle nesne kimlikleri üzerinden). Tam bir davranış sağlamak için yeterli sayıda yöntemin uygulanması gerekir ya da functools.total_ordering kullanılabilir.
Python'da diğer dillerde olduğu gibi compare(x, y) neden yok?
Python, her operatör için özel "sihirli" yöntemler fikrini miras almıştır ve cmp işlevi Python 3 ile kaldırılmıştır. Genel nesne karşılaştırmaları için zengin karşılaştırma yöntemleri (lt, eq vb.) kullanılır ve sıralama için ise sort/sorted fonksiyonlarındaki key parametresi kullanılır.
Bir nesne, gerekli yöntemin uygulanmadığı bir türle karşılaştırıldığında ne olur?
eq veya diğer yöntemlerde uygun olmayan türler için NotImplemented döndürülürse, Python otomatik olarak ikinci operandın ters yöntemini deneyecek veya False döndürecektir. Bu durumu ele almazsanız, TypeError veya tamamen yanlış bir davranışla karşılaşabilirsiniz.
Kod örneği:
class Foo: def __eq__(self, other): return NotImplemented class Bar: pass print(Foo() == Bar()) # False (Bar.__eq__ üzerinden deneme)
Bir geliştirici, User sınıfını oluşturdu ve sadece email üzerinden eşitliği sağlamak için eq'yi uyguladı fakat hash'ı uygulamayı unuttu. Kullanıcı nesnelerini set'e veya sözlük anahtarları olarak kullanmaya çalıştı.
Artılar:
Eksiler:
Bir programcı, @total_ordering kullanarak ve tipi kontrol eden eq ve lt'yi uygulayarak, sınıf değişmezse hash ekler. Nesneler doğru bir şekilde karşılaştırılır, sıralanır, sözlük anahtarları olarak işlev görür.
Artılar:
Eksiler: