Soru tarihi:
Python'da nesnelerin değeri üzerinden karşılaştırması, '==' operatörü aracılığıyla gerçekleşir ve bu arka planda eq metodunu çağırır. Bu metodun varsayılan davranışı object'ten miras alınır ve nesnelerin kimliğini karşılaştırır (çoğu sınıf için).
Sorun:
Kullanıcı tanımlı sınıfların örneklerinin anlamlı bir şekilde karşılaştırılmasını istediğimizde (örneğin, iki farklı Person nesnesi aynı veri kümesine sahip olduğunda eşit kabul edilmesi gibi), standart davranış yeterli değildir - karşılaştırmanın nasıl gerçekleştiğini açıkça tanımlamak gerekmektedir.
Çözüm:
'==' davranışını değiştirmek için kendi sınıfınızda eq metodunu yeniden tanımlamalısınız. Sınıfın hash'lenebilir olması gerekiyorsa, hash metodunu da yeniden tanımlamanız gerekmektedir.
Kod örneği:
class Person: def __init__(self, name, age): self.name = name self.age = age def __eq__(self, other): if not isinstance(other, Person): return NotImplemented return self.name == other.name and self.age == other.age p1 = Person("Ann", 25) p2 = Person("Ann", 25) print(p1 == p2) # True
Anahtar özellikler:
'==' karşılaştırması farklı türdeki nesneler için her zaman simetrik midir?
Zorunlu değildir - eğer ilk nesne NotImplemented dönerse, ters karşılaştırma gerçekleştirilir. Aksi takdirde asimetrik olabilir.
class A: def __eq__(self, other): return True class B: pass print(A() == B()) # True print(B() == A()) # False
Eğer eq uygulanmazsa, tek bir kullanıcı tanımlı sınıfın nesneleri nasıl karşılaştırılır?
Kimlik (bellek içindeki kimlik, niteliklerin değerleri yerine) karşılaştırılacaktır.
class Foo: def __init__(self, x): self.x = x f1 = Foo(5) f2 = Foo(5) print(f1 == f2) # False
Sözlük anahtarları olması gereken nesneler için hash olmadan eq tanımlamak mümkün müdür?
Hayır. Eğer eq değiştirilirse, hash'in de tanımlanması önerilir; aksi takdirde nesne hash'lenemez hale gelir (anahtar olarak kullanımında TypeError alırsınız).
class Foo: def __eq__(self, other): return True # hash object'ten miras alır, ancak davranış öngörülemez olacaktır. # Daha iyisi __hash__'i açıkça tanımlamak
Olumsuz vaka
ValueObject sınıfını tasarlarken ekip, sadece eq'yi uyguladıklarını ama hash'i unuttuklarını göz ardı ettiler. Nesneyi bir sözlük anahtarı veya bir kümenin elemanı olarak kullanmaya çalışırken TypeError hatasıyla karşılaştılar.
Artılar:
Kullanıcı tanımlı karşılaştırmanın hızlı uygulanması.
Eksiler:
Nesneleri kümelerde ve sözlüklerde kullanma imkânının olmaması, hata ayıklamada zorluk.
Olumlu vaka
Farklı bir projede geliştiriciler, her iki metodu -- eq ve hash'i açık bir biçimde uyguladılar ve kesin bir kurala uydular: Eğer iki nesne eq tarafından eşit kabul ediliyorsa, hash'leri de eşit olmalıdır.
Artılar:
Hash'li yapılarda düzgün çalışma, tutarlı davranış, bakım kolaylığı.
Eksiler:
Esneklik kaybı: değerleri eşit nesneler hash kapsayıcılarında ayırt edilemez hale gelir.