Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimanakah anda memastikan perbandingan kesetaraan yang konsisten dan mantap untuk kelas Python tersuai, terutamanya apabila berurusan dengan subkelas dan set?

Bagaimanakah anda memastikan perbandingan kesetaraan yang konsisten dan mantap untuk kelas Python tersuai, terutamanya apabila berurusan dengan subkelas dan set?

Linda Hamilton
Linda Hamiltonasal
2024-11-09 04:50:02358semak imbas

How do you ensure consistent and robust equivalence comparisons for custom Python classes, especially when dealing with subclasses and sets?

Pendekatan Elegan untuk Perbandingan Kesetaraan dalam Kelas Python

Dalam Python, kelas tersuai boleh melaksanakan kaedah __eq__ dan __ne__ untuk menentukan kesetaraan untuk operator == dan !=, masing-masing. Walaupun kaedah tradisional untuk membandingkan atribut kamus adalah mudah, ia memberikan batasan tertentu.

Pendekatan Lebih Diperhalusi

Pertimbangkan senario berikut:

class Number:
    def __init__(self, number):
        self.number = number

n1 = Number(1)
n2 = Number(1)

# Default comparison fails: they are different objects
assert n1 != n2

Untuk menangani isu ini , kita boleh mengatasi kaedah __eq__:

class Number:
    def __init__(self, number):
        self.number = number

    def __eq__(self, other):
        if isinstance(other, Number):
            return self.number == other.number
        return False

Walau bagaimanapun, untuk Python 2, kita juga perlu melaksanakan __ne__ untuk memastikan tingkah laku komutatif:

class Number:
    def __init__(self, number):
        self.number = number

    def __eq__(self, other):
        if isinstance(other, Number):
            return self.number == other.number
        return False

    def __ne__(self, other):
        return not self.__eq__(other)

Ini memastikan n1 == n2 menilai kepada Benar, seperti yang dijangkakan.

Kesamaan Subkelas

Memperkenalkan subkelas merumitkan perbandingan kesetaraan:

class SubNumber(Number):
    pass

n3 = SubNumber(1)

# Subclass comparison fails for classic-style classes
assert n1 == n3  # False (for classic-style classes)
assert n3 == n1  # True

# Non-commutative comparison
assert n1 != n3  # True (for classic-style classes)
assert n3 != n1  # False

Untuk kelas gaya klasik, kaedah perbandingan digunakan berdasarkan jenis operan pertama, yang membawa kepada tingkah laku bukan komutatif. Untuk menangani perkara ini, kami boleh mengembalikan NotImplemented untuk jenis operan yang tidak disokong, yang mewakilkan perbandingan kepada kaedah operan lain:

def __eq__(self, other):
    if isinstance(other, Number):
        return self.number == other.number
    return NotImplemented

Pencincangan dan Set

Akhir sekali, ambil perhatian bahawa set menggunakan pengecam objek untuk pencincangan, yang boleh membawa kepada hasil yang salah:

assert len(set([n1, n2, n3])) == 3  # Incorrectly reports 3 unique numbers

Untuk menyelesaikan masalah ini, kami boleh mengatasi kaedah __hash__:

def __hash__(self):
    return hash(tuple(sorted(self.__dict__.items())))

Dengan peningkatan ini, tingkah laku kesetaraan dan keunikan menjadi betul dan konsisten, memastikan perbandingan yang mantap dan perwakilan yang tepat dalam set:

assert len(set([n1, n2, n3])) == 1
assert len(set([n1, n2, n3, n4])) == 2

Atas ialah kandungan terperinci Bagaimanakah anda memastikan perbandingan kesetaraan yang konsisten dan mantap untuk kelas Python tersuai, terutamanya apabila berurusan dengan subkelas dan set?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn