Anda harus menerapkan metode ini __eq__
:
class MyClass:
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
def __eq__(self, other):
if not isinstance(other, MyClass):
# don't attempt to compare against unrelated types
return NotImplemented
return self.foo == other.foo and self.bar == other.bar
Sekarang ini menghasilkan:
>>> x == y
True
Perhatikan bahwa implementasi __eq__
akan secara otomatis membuat instance dari kelas Anda tidak dapat diakses, yang berarti mereka tidak dapat disimpan dalam set dan dikte. Jika Anda tidak memodelkan tipe yang tidak dapat diubah (yaitu jika atribut foo
dan bar
dapat mengubah nilai dalam masa hidup objek Anda), maka disarankan untuk membiarkan saja instance Anda sebagai yang tidak dapat pecah.
Jika Anda memodelkan tipe yang tidak dapat diubah, Anda juga harus mengimplementasikan kait model data __hash__
:
class MyClass:
...
def __hash__(self):
# necessary for instances to behave sanely in dicts and sets.
return hash((self.foo, self.bar))
Solusi umum, seperti ide untuk melakukan perulangan __dict__
dan membandingkan nilai, tidak disarankan - solusi ini tidak pernah benar-benar umum karena __dict__
mungkin memiliki jenis yang tidak dapat dibandingkan atau tidak dapat dihancurkan yang terkandung di dalamnya.
NB: menyadari bahwa sebelum Python 3, Anda mungkin perlu menggunakan __cmp__
bukan __eq__
. Pengguna Python 2 mungkin juga ingin menerapkan __ne__
, karena perilaku default yang masuk akal untuk ketidaksetaraan (yaitu membalikkan hasil kesetaraan) tidak akan secara otomatis dibuat di Python 2.
return NotImplemented
(bukannya meningkatkanNotImplementedError
). Topik itu dibahas di sini: stackoverflow.com/questions/878943/…Anda menimpa operator perbandingan kaya di objek Anda.
Seperti ini:
sumber
__eq__()
, tetapi hanya satu dari__lt__()
,__le__()
,__gt__()
, atau__ge__()
dibutuhkan selain itu. Dari situ, Python dapat menyimpulkan metode lain. Lihatfunctools
untuk informasi lebih lanjut.functools
modul, tetapi tidak berfungsi untuk pembanding standar:MyObj1 != Myobj2
hanya akan berfungsi jika__ne__()
metode ini diterapkan.@functools.total_ordering
dekorator di kelas Anda, maka seperti di atas Anda dapat mendefinisikan adil__eq__
dan satu lainnya dan sisanya akan diturunkanTerapkan
__eq__
metode di kelas Anda; sesuatu seperti ini:Sunting: jika Anda ingin objek Anda untuk membandingkan sama jika dan hanya jika mereka memiliki kamus contoh yang sama:
sumber
self is other
melihat apakah mereka adalah objek yang sama.AttributeError
. Anda harus memasukkan barisif hasattr(other, "path") and hasattr(other, "title"):
(seperti contoh yang bagus di dokumentasi Python).Sebagai ringkasan:
__eq__
daripada__cmp__
, kecuali jika Anda menjalankan python <= 2.0 (__eq__
telah ditambahkan pada 2.1)__ne__
(harus sepertireturn not self.__eq__(other)
ataureturn not self == other
kecuali kasus yang sangat khusus)Jika Anda ingin membandingkan dengan objek yang bisa menjadi Tidak Ada, Anda harus mengimplementasikannya. Penerjemah tidak dapat menebaknya ... (lihat contoh di bawah)
sumber
Tergantung pada kasus spesifik Anda, Anda dapat melakukan:
Lihat kamus Python dari bidang objek
sumber
Dengan Dataclasses di Python 3.7 (dan di atas), perbandingan instance objek untuk kesetaraan adalah fitur bawaan.
Sebuah backport untuk Dataclasses yang tersedia untuk Python 3.6.
sumber
Saat membandingkan instance objek,
__cmp__
fungsinya disebut.Jika operator == tidak bekerja untuk Anda secara default, Anda selalu dapat mendefinisikan kembali
__cmp__
fungsi untuk objek.Edit:
Seperti yang telah ditunjukkan,
__cmp__
fungsi ini sudah tidak digunakan lagi sejak 3.0. Sebaliknya, Anda harus menggunakan metode "perbandingan kaya" .sumber
Jika Anda berurusan dengan satu atau beberapa kelas yang tidak dapat Anda ubah dari dalam, ada cara umum dan sederhana untuk melakukan ini yang juga tidak bergantung pada pustaka khusus:
Metode objek termudah, tidak aman untuk objek yang sangat kompleks
pickle
adalah lib serialisasi yang sangat umum untuk objek Python, dan dengan demikian akan dapat membuat serialisasi apa saja, sungguh. Dalam cuplikan di atas saya membandingkanstr
dari seriala
dengan yang darib
. Berbeda dengan metode selanjutnya, yang satu ini memiliki keuntungan juga mengetik kelas kustom.Kerumitan terbesar: karena pemesanan khusus dan metode pengkodean,
pickle
tidak dapat menghasilkan hasil yang sama untuk objek yang sama , khususnya ketika berhadapan dengan yang lebih kompleks (mis. Daftar instance kelas kustom bersarang) seperti Anda akan sering menemukan di beberapa lib pihak ketiga. Untuk kasus-kasus itu, saya akan merekomendasikan pendekatan yang berbeda:Metode objek yang menyeluruh, aman untuk apa saja
Anda bisa menulis refleksi rekursif yang akan memberi Anda objek serial, dan kemudian membandingkan hasilnya
Sekarang tidak masalah apa objek Anda, kesetaraan yang dalam dijamin untuk bekerja
Jumlah yang sebanding tidak masalah juga
Kasus penggunaan saya untuk ini adalah memeriksa kesetaraan yang mendalam di antara beragam model Pembelajaran Mesin yang sudah terlatih dalam tes BDD. Model-model tersebut milik beragam set lib pihak ketiga. Tentunya menerapkan
__eq__
seperti jawaban lain di sini menyarankan bukan pilihan bagi saya.Menutupi semua pangkalan
Anda mungkin berada dalam skenario di mana satu atau beberapa kelas khusus yang dibandingkan tidak memiliki
__dict__
implementasi . Itu tidak umum dengan cara apapun, tapi itu adalah kasus subtipe dalam classifier Acak Hutan sklearn ini:<type 'sklearn.tree._tree.Tree'>
. Perlakukan situasi ini dalam kasus per kasus - misalnya secara spesifik , saya memutuskan untuk mengganti konten dari jenis yang diderita dengan konten dari metode yang memberi saya informasi yang representatif pada contoh (dalam kasus ini,__getstate__
metode). Untuk itu, baris kedua ke terakhirbase_typed
menjadiSunting: demi organisasi, saya mengganti dua baris terakhir
base_typed
denganreturn dict_from(obj)
, dan menerapkan refleksi yang benar-benar umum untuk mengakomodasi lebih banyak lib yang tidak jelas (Saya melihat Anda, Doc2Vec)Jangan pedulikan metode di atas menghasilkan
True
objek yang berbeda dengan pasangan nilai kunci yang sama tetapi pesanan kunci / nilai yang berbeda, seperti padaTetapi jika Anda mau, Anda bisa menggunakan
sorted
metode bawaan Python sebelumnya.sumber
Saya menulis ini dan meletakkannya dalam
test/utils
modul di proyek saya. Untuk kasus-kasus ketika itu bukan kelas, hanya merencanakan dict, ini akan melintasi kedua objek dan memastikanBesar ... tidak seksi ... tapi oh, boi berhasil!
Anda dapat membersihkannya sedikit dengan menghapus
_assert
dan hanya menggunakan ol 'assert
tetapi kemudian pesan yang Anda dapatkan ketika gagal sangat tidak membantu.sumber
Anda harus menerapkan metode ini
__eq__
:sumber
Di bawah ini berfungsi (dalam pengujian terbatas saya) dengan melakukan perbandingan mendalam antara dua hierarki objek. Dalam menangani berbagai kasus termasuk kasus-kasus ketika objek itu sendiri atau atributnya adalah kamus.
Ini adalah kode yang sangat rumit, jadi tolong tambahkan setiap kasus yang mungkin tidak berfungsi untuk Anda dalam komentar.
sumber
sumber
Jika Anda ingin mendapatkan perbandingan atribut-per-atribut, dan melihat apakah dan di mana gagal, Anda dapat menggunakan pemahaman daftar berikut:
Keuntungan tambahan di sini adalah Anda bisa menekannya satu baris dan masukkan di jendela "Evaluate Expression" saat melakukan debug di PyCharm.
sumber
Saya mencoba contoh awal (lihat 7 di atas) dan tidak berhasil di ipython. Perhatikan bahwa cmp (obj1, obj2) mengembalikan "1" ketika diimplementasikan menggunakan dua instance objek yang identik. Anehnya ketika saya memodifikasi salah satu nilai atribut dan membandingkannya, menggunakan cmp (obj1, obj2) objek terus mengembalikan "1". (mendesah...)
Ok, jadi yang perlu Anda lakukan adalah mengulangi dua objek dan membandingkan setiap atribut menggunakan tanda ==.
sumber
Contoh kelas jika dibandingkan dengan == datang ke non-sama. Cara terbaik adalah dengan memasukkan fungsi cmp ke kelas Anda yang akan melakukan hal-hal tersebut.
Jika Anda ingin melakukan perbandingan dengan konten Anda cukup menggunakan cmp (obj1, obj2)
Dalam kasus Anda cmp (doc1, doc2) Ini akan mengembalikan -1 jika kontennya sama.
sumber