ProgramlamaMiddle Python разработчик

Python'da '==' karşılaştırma operatörünün ve __eq__ metodunun işleyişi ne ile belirlenir? Kendi sınıflarınız için karşılaştırma davranışını nasıl değiştirebilirsiniz?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

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:

  • '==' eq'yi çağırır.
  • eq olmadan nesnelerin karşılaştırılmasında kimlikleri (id) karşılaştırılacaktır.
  • Küme/dictionary'lerle düzgün çalışmak için hash da uygulanmalıdır.

Kandırma Soruları.

'==' 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

Tipik hatalar ve anti-paternerler

  • dict/set'te anahtar gerektiren yerlerde hash olmadan eq uygulaması.
  • Farklı türlerdeki nesnelerle karşılaştırmada hata (NotImplemented döndürmek yerine False dönmek gerekir).
  • eq ve hash'in tutarsız tanımlanması, hash'li yapılarda yanlış davranışlara yol açabilir.

Gerçek yaşam örneği

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.