Saya memiliki kelas di mana saya ingin mengganti __eq__
metode ini. Tampaknya masuk akal bahwa saya harus menimpa __ne__
metode juga, tapi tidak masuk akal untuk menerapkan __ne__
dalam hal __eq__
seperti itu?
class A:
def __init__(self, attr):
self.attr = attr
def __eq__(self, other):
return self.attr == other.attr
def __ne__(self, other):
return not self.__eq__(other)
Atau apakah ada sesuatu yang saya lewatkan dengan cara Python menggunakan metode ini yang membuat ini bukan ide yang bagus?
sumber
__ne__
menggunakan__eq__
, hanya bahwa Anda menerapkannya.NotImplemented
pengembalian dari satu sisi sebagai isyarat untuk didelegasikan ke__ne__
sisi lain,not self == other
adalah (dengan asumsi operan__eq__
tidak tahu bagaimana membandingkan operan lain) secara implisit mendelegasikan ke__eq__
dari sisi lain, kemudian membalikkannya. Untuk tipe aneh, misalnya kolom SQLAlchemy ORM, ini menyebabkan masalah .__ne__
secara otomatis didelegasikan ke__eq__
dan kutipan dalam jawaban ini tidak lagi ada di dokumen. Intinya adalah pythonic sempurna untuk hanya mengimplementasikan__eq__
dan membiarkan__ne__
mendelegasikan.Jawaban Singkat: Jangan terapkan, tetapi jika harus, gunakan
==
, jangan__eq__
Dalam Python 3,
!=
negasi dari==
secara default, jadi Anda bahkan tidak diharuskan untuk menulis__ne__
, dan dokumentasinya tidak lagi beropini untuk menulisnya.Secara umum, untuk kode Python 3-saja, jangan menulisnya kecuali Anda perlu menaungi implementasi induk, misalnya untuk objek bawaan.
Artinya, ingatlah komentar Raymond Hettinger :
Jika Anda membutuhkan kode Anda untuk bekerja dengan Python 2, ikuti rekomendasi untuk Python 2 dan itu akan bekerja dengan baik di Python 3.
Di Python 2, Python sendiri tidak secara otomatis mengimplementasikan operasi apa pun dalam istilah lain - oleh karena itu, Anda harus mendefinisikan
__ne__
in==
daripada__eq__
. MISALNYALihat buktinya
__ne__()
operator pelaksana berdasarkan__eq__
dan__ne__
di Python 2 sama sekalimemberikan perilaku yang salah dalam demonstrasi di bawah ini.
Jawaban panjang
The dokumentasi untuk Python 2 mengatakan:
Artinya, jika kita mendefinisikan
__ne__
kebalikan dari__eq__
, kita bisa mendapatkan perilaku yang konsisten.Bagian dokumentasi ini telah diperbarui untuk Python 3:
dan di bagian "apa yang baru" , kami melihat perilaku ini telah berubah:
Untuk mengimplementasikan
__ne__
, kami lebih suka menggunakan==
operator daripada menggunakan__eq__
metode secara langsung sehingga jikaself.__eq__(other)
subclass mengembalikanNotImplemented
untuk tipe yang dicentang, Python akan memeriksaother.__eq__(self)
Dari dokumentasi dengan tepat :Ketika diberi operator perbandingan yang kaya, jika mereka bukan tipe yang sama, cek Python jika
other
adalah subtipe, dan jika memiliki bahwa operator didefinisikan, menggunakanother
metode 's pertama (inverse untuk<
,<=
,>=
dan>
). JikaNotImplemented
dikembalikan, maka itu menggunakan metode sebaliknya. (Ini tidak memeriksa metode yang sama dua kali.) Menggunakan==
operator memungkinkan logika ini berlangsung.Harapan
Secara semantik, Anda harus mengimplementasikan
__ne__
dalam hal pemeriksaan kesetaraan karena pengguna kelas Anda akan mengharapkan fungsi berikut setara untuk semua instance A:Artinya, kedua fungsi di atas harus selalu mengembalikan hasil yang sama. Tapi ini tergantung pada programmernya.
Demonstrasi perilaku tak terduga saat mendefinisikan
__ne__
berdasarkan__eq__
:Pertama penyiapan:
Instantiate instance yang tidak setara:
Perilaku yang Diharapkan:
(Catatan: meskipun pernyataan setiap detik dari masing-masing pernyataan di bawah ini setara dan oleh karena itu secara logis berlebihan dengan pernyataan sebelumnya, saya menyertakan pernyataan tersebut untuk menunjukkan bahwa urutan tidak menjadi masalah jika salah satu merupakan subkelas dari yang lain. )
Instance ini telah
__ne__
diimplementasikan dengan==
:Instance ini, yang diuji dengan Python 3, juga bekerja dengan benar:
Dan ingat bahwa ini telah
__ne__
diterapkan dengan__eq__
- meskipun ini adalah perilaku yang diharapkan, penerapannya salah:Perilaku Tak Terduga:
Perhatikan bahwa perbandingan ini bertentangan dengan perbandingan di atas (
not wrong1 == wrong2
).dan,
Jangan lewati
__ne__
dengan Python 2Untuk bukti bahwa Anda tidak boleh melewatkan penerapan
__ne__
di Python 2, lihat objek yang setara ini:Hasil di atas seharusnya
False
!Sumber Python 3
Implementasi CPython default untuk
__ne__
adatypeobject.c
diobject_richcompare
:Tapi default
__ne__
menggunakan__eq__
?__ne__
Detail implementasi default Python 3 di level C digunakan__eq__
karena level yang lebih tinggi==
( PyObject_RichCompare ) akan kurang efisien - dan oleh karena itu ia juga harus menanganiNotImplemented
.Jika
__eq__
diterapkan dengan benar, maka negasi dari==
juga benar - dan ini memungkinkan kita untuk menghindari detail implementasi tingkat rendah di__ne__
.Menggunakan
==
memungkinkan kita untuk menjaga logika rendah tingkat kami di satu tempat, dan menghindari menanganiNotImplemented
di__ne__
.Orang mungkin salah berasumsi bahwa
==
mungkin kembaliNotImplemented
.Ini sebenarnya menggunakan logika yang sama dengan implementasi default
__eq__
, yang memeriksa identitas (lihat do_richcompare dan bukti kami di bawah)Dan perbandingannya:
Performa
Jangan percaya kata-kata saya untuk itu, mari kita lihat apa yang lebih berkinerja:
Saya pikir angka-angka kinerja ini berbicara sendiri:
Ini masuk akal ketika Anda mempertimbangkan bahwa
low_level_python
melakukan logika dengan Python yang seharusnya ditangani pada level C.Tanggapan untuk beberapa kritikus
Penjawab lain menulis:
Tidak
__ne__
pernah kembaliNotImplemented
tidak membuatnya salah. Sebaliknya, kami menangani prioritas denganNotImplemented
melalui check for equality with==
. Dengan asumsi==
diterapkan dengan benar, kita sudah selesai.Baiklah, mari kita jelaskan ini.
Seperti disebutkan sebelumnya, Python 3 secara default menangani
__ne__
dengan terlebih dahulu memeriksa apakahself.__eq__(other)
returnNotImplemented
(a singleton) - yang harus diperiksa denganis
dan dikembalikan jika demikian, kalau tidak ia harus mengembalikan inversnya. Berikut adalah logika yang ditulis sebagai campuran kelas:Ini diperlukan untuk kebenaran untuk API Python tingkat C, dan itu diperkenalkan di Python 3, membuat
__ne__
metode dalam patch ini untuk dekat Issue 21.408 dan__ne__
metode dalam tindak-on pembersihan dihapus disinimubazir. Semua
__ne__
metode yang relevan telah dihapus, termasuk metode yang menerapkan pemeriksaan mereka sendiri serta metode yang didelegasikan__eq__
secara langsung atau melalui==
- dan==
merupakan cara paling umum untuk melakukannya.Apakah Simetri Penting?
Kritikus gigih kami memberikan contoh patologis untuk membuat kasus untuk penanganan
NotImplemented
di__ne__
, menilai simetri di atas segalanya. Mari kita menguatkan argumen dengan contoh yang jelas:Jadi, dengan logika ini, untuk menjaga simetri, kita perlu menulis rumit
__ne__
, apa pun versi Pythonnya.Rupanya kita tidak perlu peduli bahwa contoh ini sama dan tidak sama.
Saya mengusulkan simetri yang kurang penting daripada praduga kode yang masuk akal dan mengikuti saran dari dokumentasi.
Namun, jika A memiliki implementasi yang masuk akal
__eq__
, maka kita masih bisa mengikuti arahan saya di sini dan kita masih memiliki simetri:Kesimpulan
Untuk kode yang kompatibel dengan Python 2, gunakan
==
untuk mengimplementasikan__ne__
. Ini lebih:Hanya dalam Python 3, gunakan negasi tingkat rendah pada tingkat C - ini bahkan lebih sederhana dan berkinerja (meskipun pemrogram bertanggung jawab untuk menentukan bahwa itu benar ).
Sekali lagi, lakukan tidak logika tingkat rendah menulis di tingkat tinggi Python.
sumber
a1 != c2
kembaliFalse
--- itu tidak berjalana1.__ne__
, tapic2.__ne__
, yang menegasikan mixin ini__eq__
metode. SejakNotImplemented
itu benar,not NotImplemented
adalahFalse
.not (self == other)
, tetapi tidak ada yang membantahnya tidak cepat (yah, lebih cepat daripada opsi lain di Py2). Masalahnya adalah salah dalam beberapa kasus; Python sendiri dulu melakukannyanot (self == other)
, tetapi berubah karena salah dengan adanya subkelas yang berubah-ubah . Jawaban tercepat sampai salah masih salah .__ne__
delegasi Anda ke__eq__
(dari kedua sisi jika perlu), tetapi tidak pernah jatuh kembali ke__ne__
sisi lain bahkan ketika keduanya__eq__
"menyerah".__ne__
Delegasi yang benar menjadi miliknya sendiri__eq__
, tetapi jika itu kembaliNotImplemented
, itu kembali untuk pergi ke pihak lain__ne__
, daripada membalikkan pihak lain__eq__
(karena pihak lain mungkin tidak secara eksplisit memilih untuk mendelegasikan__eq__
, dan Anda tidak seharusnya membuat keputusan itu untuk itu).__eq__
atau__ne__
mengembalikan salah satuTrue
atauFalse
, melainkan objek proxy (yang kebetulan "benar"). Penerapan yang salah__ne__
berarti urutan penting untuk perbandingan (Anda hanya mendapatkan proxy dalam satu urutan).__ne__
sepenuhnya. Setahun dari sekarang, Py2 akan mati dan kita abaikan ini. :-)Sekadar catatan, portabel Py2 / Py3 yang benar dan silang secara kanonik
__ne__
akan terlihat seperti:Ini berfungsi dengan apa pun
__eq__
yang mungkin Anda tentukan:not (self == other)
, tidak mengganggu dalam beberapa kasus yang mengganggu / kompleks yang melibatkan perbandingan di mana salah satu kelas yang terlibat tidak berarti bahwa hasil__ne__
adalah sama dengan hasilnot
pada__eq__
(ORM misalnya SQLAlchemy, di mana baik__eq__
dan__ne__
kembali proksi benda-benda khusus, tidakTrue
atauFalse
, dan mencobanot
hasil__eq__
akan kembaliFalse
, bukan objek proxy yang benar).not self.__eq__(other)
, ini dengan benar mendelegasikan ke__ne__
contoh lain ketikaself.__eq__
kembaliNotImplemented
(not self.__eq__(other)
akan sangat salah, karenaNotImplemented
benar, jadi ketika__eq__
tidak tahu bagaimana melakukan perbandingan,__ne__
akan kembaliFalse
, menyiratkan bahwa kedua objek itu sama padahal sebenarnya satu-satunya objek yang ditanyakan tidak tahu, yang berarti default tidak sama)Jika Anda
__eq__
tidak menggunakanNotImplemented
pengembalian, ini berfungsi (dengan overhead yang tidak berarti), jikaNotImplemented
kadang-kadang digunakan , ini menanganinya dengan benar. Dan pemeriksaan versi Python berarti bahwa jika kelasnya diberi-import
di Python 3,__ne__
dibiarkan tidak terdefinisi, memungkinkan__ne__
implementasi fallback asli dan efisien Python (versi C di atas) untuk mengambil alih.Mengapa ini dibutuhkan
Aturan overloading Python
Penjelasan mengapa Anda melakukan ini dan bukan solusi lain agak misterius. Python memiliki beberapa aturan umum tentang operator overloading, dan operator perbandingan khususnya:
LHS OP RHS
, cobaLHS.__op__(RHS)
, dan jika berhasilNotImplemented
, cobaRHS.__rop__(LHS)
. Pengecualian: JikaRHS
merupakan subclass dariLHS
kelas, maka ujiRHS.__rop__(LHS)
terlebih dahulu . Dalam kasus operator pembanding,__eq__
dan__ne__
merupakan "rop" mereka sendiri (jadi urutan pengujiannya__ne__
adalahLHS.__ne__(RHS)
, kemudianRHS.__ne__(LHS)
, dibalik jikaRHS
adalah subclass dariLHS
kelasnya)LHS.__eq__(RHS)
mengembalikanTrue
tidak berartiLHS.__ne__(RHS)
mengembalikanFalse
(pada kenyataannya, operator bahkan tidak diharuskan untuk mengembalikan nilai boolean; ORM seperti SQLAlchemy sengaja tidak melakukannya, memungkinkan sintaks kueri yang lebih ekspresif). Pada Python 3,__ne__
implementasi default berperilaku seperti ini, tetapi tidak kontraktual; Anda dapat menimpa__ne__
dengan cara yang tidak berlawanan__eq__
.Bagaimana ini berlaku untuk pembanding yang kelebihan beban
Jadi, saat Anda membebani operator, Anda memiliki dua pekerjaan:
NotImplemented
, sehingga Python dapat mendelegasikan ke implementasi operan lainMasalah dengan
not self.__eq__(other)
tidak pernah mendelegasikan ke pihak lain (dan tidak benar jika
__eq__
dikembalikan dengan benarNotImplemented
). Ketikaself.__eq__(other)
kembaliNotImplemented
(yang "benar"), Anda diam-diam kembaliFalse
, jadiA() != something_A_knows_nothing_about
mengembalikanFalse
, ketika seharusnya diperiksa apakahsomething_A_knows_nothing_about
tahu bagaimana membandingkan dengan contohA
, dan jika tidak, itu seharusnya dikembalikanTrue
(karena jika tidak ada pihak yang tahu bagaimana caranya dibandingkan dengan yang lain, mereka dianggap tidak setara satu sama lain). JikaA.__eq__
diimplementasikan secara tidak benar (mengembalikanFalse
bukannyaNotImplemented
ketika tidak mengenali sisi lain), maka ini adalah "benar" dariA
perspektif, kembaliTrue
(karenaA
tidak menganggapnya sama, jadi tidak sama), tetapi mungkin saja salah darisomething_A_knows_nothing_about
perspektif, karena tidak pernah ditanyasomething_A_knows_nothing_about
;A() != something_A_knows_nothing_about
berakhirTrue
, tapisomething_A_knows_nothing_about != A()
bisaFalse
, atau nilai kembali lainnya.Masalah dengan
not self == other
lebih halus. Ini akan benar untuk 99% kelas, termasuk semua kelas yang
__ne__
merupakan invers logis dari__eq__
. Tapinot self == other
melanggar kedua aturan yang disebutkan di atas, yang berarti untuk kelas di mana__ne__
bukan invers logis__eq__
, hasilnya sekali lagi non-simetris, karena salah satu operan tidak pernah ditanya apakah dapat diimplementasikan__ne__
sama sekali, bahkan jika yang lain operan tidak bisa. Contoh paling sederhana adalah kelas aneh yang kembaliFalse
untuk semua perbandingan, sehinggaA() == Incomparable()
danA() != Incomparable()
keduanya kembaliFalse
. Dengan implementasi yang benarA.__ne__
(yang kembaliNotImplemented
ketika tidak tahu bagaimana melakukan perbandingan), hubungannya simetris;A() != Incomparable()
danIncomparable() != A()
setuju pada hasil (karena dalam kasus pertama,A.__ne__
kembaliNotImplemented
, kemudianIncomparable.__ne__
kembaliFalse
, sedangkan dalam kasus terakhir,Incomparable.__ne__
kembaliFalse
secara langsung). Tapi ketikaA.__ne__
diimplementasikan sebagaireturn not self == other
,A() != Incomparable()
mengembalikanTrue
(karenaA.__eq__
mengembalikan, bukanNotImplemented
, laluIncomparable.__eq__
mengembalikanFalse
, danA.__ne__
membalikkannya menjadiTrue
), sementaraIncomparable() != A()
mengembalikanFalse.
Anda dapat melihat contohnya di sini .
Jelas, kelas yang selalu kembali
False
untuk keduanya__eq__
dan__ne__
sedikit aneh. Tapi seperti yang disebutkan sebelumnya,__eq__
dan__ne__
bahkan tidak perlu mengembalikanTrue
/False
; ORM SQLAlchemy memiliki kelas dengan pembanding yang mengembalikan objek proxy khusus untuk pembuatan kueri, bukanTrue
/False
sama sekali (mereka "benar" jika dievaluasi dalam konteks boolean, tetapi mereka tidak pernah seharusnya dievaluasi dalam konteks seperti itu).Dengan gagal membebani
__ne__
dengan benar, Anda akan merusak kelas semacam itu, sebagai kode:akan berfungsi (dengan asumsi SQLAlchemy sama sekali tahu cara memasukkan
MyClassWithBadNE
ke dalam string SQL; ini dapat dilakukan dengan adaptor tipe tanpaMyClassWithBadNE
harus bekerja sama sama sekali), meneruskan objek proxy yang diharapkan kefilter
, sementara:akan berakhir
filter
dengan polosFalse
, karenaself == other
mengembalikan objek proxy, dannot self == other
hanya mengubah objek proxy yang benar menjadiFalse
. Mudah-mudahan,filter
melempar pengecualian saat menangani argumen yang tidak valid sepertiFalse
. Meskipun saya yakin banyak yang akan berpendapat bahwaMyTable.fieldname
seharusnya secara konsisten berada di sisi kiri perbandingan, faktanya tetap bahwa tidak ada alasan terprogram untuk memberlakukan ini dalam kasus umum, dan generik yang benar__ne__
akan berfungsi dengan cara apa pun, sementarareturn not self == other
hanya berfungsi dalam satu pengaturan.sumber
Incomparable
kelas sejak kelas ini istirahat yang pelengkap hubungan antara!=
dan==
operator dan karena itu mungkin dianggap tidak valid atau "patologis" Misalnya seperti @AaronHall meletakkannya. Dan saya akui bahwa @AaronHall ada benarnya ketika dia menunjukkan bahwa argumen SQLAlchemy Anda mungkin dianggap tidak relevan karena berada dalam konteks non-Boolean. (Argumen Anda masih sangat menarik dan dipikirkan dengan baik.)__ne__
Implementasi yang benarImplementasi @ ShadowRanger untuk metode khusus
__ne__
adalah yang benar:Ini juga merupakan implementasi default dari metode khusus
__ne__
sejak Python 3.4 , seperti yang dinyatakan dalam dokumentasi Python :Perhatikan juga bahwa mengembalikan nilai
NotImplemented
untuk operand yang tidak didukung tidak spesifik untuk metode khusus__ne__
. Faktanya, semua metode perbandingan khusus 1 dan metode numerik khusus 2 harus mengembalikan nilaiNotImplemented
untuk operan yang tidak didukung , seperti yang ditentukan dalam dokumentasi Python :Contoh untuk metode numerik khusus diberikan dalam dokumentasi Python :
1 Metode perbandingan khusus:
__lt__
,__le__
,__eq__
,__ne__
,__gt__
dan__ge__
.2 Metode numerik khusus:
__add__
,__sub__
,__mul__
,__matmul__
,__truediv__
,__floordiv__
,__mod__
,__divmod__
,__pow__
,__lshift__
,__rshift__
,__and__
,__xor__
,__or__
dan mereka__r*__
tercermin dan__i*__
di tempat rekan-rekan.__ne__
Penerapan yang salah # 1Implementasi @ Falmarri atas metode khusus
__ne__
salah:Masalah dengan implementasi ini adalah ia tidak kembali ke metode khusus
__ne__
dari operan lain karena tidak pernah mengembalikan nilaiNotImplemented
(ekspresinot self.__eq__(other)
mengevaluasi ke nilaiTrue
atauFalse
, termasuk ketika subekspresiself.__eq__(other)
mengevaluasi ke nilaiNotImplemented
sejakbool(NotImplemented)
ituTrue
). Evaluasi nilai BooleanNotImplemented
memutuskan hubungan komplemen antara operator!=
dan==
:__ne__
Penerapan yang salah # 2Implementasi @ AaronHall untuk metode khusus
__ne__
juga salah:Masalah dengan implementasi ini adalah ia secara langsung kembali ke metode khusus
__eq__
dari operan lain, melewati metode khusus__ne__
dari operan lain karena tidak pernah mengembalikan nilaiNotImplemented
(ekspresinot self == other
jatuh kembali ke metode khusus__eq__
dari operan lain dan mengevaluasi ke nilaiTrue
atauFalse
). Melewati metode tidak benar karena metode itu mungkin memiliki efek samping seperti memperbarui status objek:Memahami operasi perbandingan
Dalam matematika, relasi biner R atas himpunan X adalah himpunan pasangan terurut ( x , y ) dalam X 2 . Pernyataan ( x , y ) di R berbunyi " x adalah R -terkait untuk y " dan dilambangkan dengan XRY .
Properti relasi biner R atas himpunan X :
Misalnya, =. Namun ≠ hanya simetris.
Misalnya, ≤ dan ≥.
Misalnya, <dan>.
Operasi pada dua relasi biner R dan S pada himpunan X :
Hubungan antar hubungan perbandingan yang selalu valid:
Hubungan antar relasi perbandingan yang hanya valid untuk perintah connex :
Jadi untuk benar menerapkan Python operator perbandingan
==
,!=
,<
,>
,<=
, dan>=
sesuai dengan hubungan perbandingan =, ≠, <,>, ≤, dan ≥, semua di atas sifat matematika dan hubungan harus terus.Python memungkinkan pengguna menyesuaikan operasi perbandingan
x operator y
dengan membebani metode perbandingan khusus operan kirinyax.__operator__(y)
:Implementasi default dari metode perbandingan khusus dijelaskan dalam dokumentasi Python :
Karena R = ( R T ) T , perbandingan xRy setara dengan perbandingan sebaliknya yR T x (secara informal dinamai "tercermin" dalam dokumentasi Python). Jadi, ada dua cara untuk menghitung hasil operasi perbandingan
x operator y
: memanggil salah satux.__operator__(y)
atauy.__operatorT__(x)
. Python menggunakan strategi komputasi berikut:x.__operator__(y)
kecuali kelas operan kanan adalah turunan dari kelas operan kiri, dalam hal ini ia memanggily.__operatorT__(x)
( mengizinkan kelas untuk mengganti metode perbandingan kebalikan khusus leluhur mereka ).x
dany
tidak didukung (ditunjukkan oleh nilai kembalianNotImplemented
), metode converse khusus dipanggil sebagai fallback pertama .x
dany
tidak didukung (ditunjukkan oleh nilai kembalianNotImplemented
), itu memunculkan pengecualianTypeError
kecuali untuk operator perbandingan==
dan!=
yang menguji masing-masing identitas dan non-identitas operanx
dany
sebagai fallback ke - 2 .Ini dapat diterjemahkan ke dalam kode Python (dengan nama
eq
untuk==
,ne
untuk!=
,lt
untuk<
,gt
untuk>
,le
untuk ,<=
dange
untuk>=
):Karena R = ¬ (¬ R ), perbandingan xRy setara dengan perbandingan komplemen ¬ ( x ¬ Ry ). ≠ adalah pelengkap dari =, jadi metode khusus
__ne__
diimplementasikan dalam istilah metode khusus__eq__
untuk operan yang didukung secara default, sedangkan metode perbandingan khusus lainnya diimplementasikan secara independen secara default (fakta bahwa ≤ adalah gabungan dari <dan =, dan ≥ adalah gabungan> dan = secara mengejutkan tidak dipertimbangkan , yang berarti saat ini metode khusus__le__
dan__ge__
harus diimplementasikan oleh pengguna), seperti yang dijelaskan dalam dokumentasi Python :Ini dapat diterjemahkan ke dalam kode Python:
Jadi secara default, operasi perbandingan
x operator y
memunculkan pengecualianTypeError
kecuali untuk operator perbandingan==
dan!=
yang mengembalikan masing-masing identitas dan non-identitas operanx
dany
.sumber
__ne__
metode ketika__eq__
metode mengembalikan NotImplemented, itu salah." -A
mendefinisikan kesetaraan tanpa syarat. JadiA() == B()
,. JadiA() != B()
seharusnya Salah , dan memang benar . Contoh yang diberikan bersifat patologis (yaitu__ne__
tidak mengembalikan string, dan__eq__
tidak bergantung pada__ne__
- melainkan__ne__
harus bergantung pada__eq__
, yang merupakan ekspektasi default dalam Python 3). Saya masih -1 pada jawaban ini sampai Anda bisa berubah pikiran.NotImplemented
jika tidak mengimplementasikan operasi untuk pasangan argumen tertentu. Secara konvensi,False
danTrue
dikembalikan untuk perbandingan yang berhasil. Namun, metode ini dapat mengembalikan nilai apa pun , jadi jika operator perbandingan digunakan dalam konteks Boolean (misalnya, dalam kondisi pernyataan if), Python akan memanggilbool()
nilai untuk menentukan apakah hasilnya benar atau salah. "B
yang mengembalikan string yang benar pada semua pemeriksaan__ne__
, danA
yang mengembalikanTrue
semua pemeriksaan untuk__eq__
. Ini adalah kontradiksi patologis. Di bawah kontradiksi seperti itu, yang terbaik adalah mengajukan pengecualian. Tanpa pengetahuanB
,A
tidak ada kewajiban untuk menghormatiB
implementasi__ne__
untuk tujuan simetri. Pada saat itu dalam contoh, bagaimanaA
mengimplementasikan__ne__
tidak relevan dengan saya. Temukan kasus praktis dan non-patologis untuk menjelaskan maksud Anda. Saya telah memperbarui jawaban saya untuk menjawab Anda.Jika semua
__eq__
,__ne__
,__lt__
,__ge__
,__le__
, dan__gt__
masuk akal untuk kelas, kemudian hanya menerapkan__cmp__
gantinya. Jika tidak, lakukan seperti yang Anda lakukan, karena sedikit yang dikatakan Daniel DiPaolo (saat saya mengujinya alih-alih mencarinya;))sumber
__cmp__()
metode khusus tidak lagi didukung dengan Python 3.x sehingga Anda harus terbiasa menggunakan operator perbandingan yang kaya.