[Python Advanced] Benutzerdefinierte Klasse: Vergleich

4.10.3 Vergleich

In Python vergleichen wir häufig zwei Datenstrukturen auf Gleichheit oder Größen. Für die in Python integrierten Datenstrukturen ist der Vergleich dieser Datenstrukturen gut definiert.
Von Benutzern selbst geschriebene Datenstrukturen müssen manchmal miteinander verglichen werden. Die logische Umsetzung des Vergleichs erfolgt durch magische Methoden.
Wenn in Python keine Vergleichslogik in der benutzerdefinierten Klasse geschrieben ist, wird diese standardmäßig für den Vergleich verwendet.

from icecream import ic


class Date:
    def __init__(self, year, month, date):
        self.year = year
        self.month = month
        self.date = date


x = Date(2022, 2, 22)
y = Date(2022, 2, 22)
ic(x == y)  # 相当于:ic(x is y)

16:34:19|> x == y: Falsch

4.10.3.1 Gl.ne

„==“ ruft diese Methode auf, wenn beurteilt wird, ob zwei Objekte gleich sind.

from icecream import ic


class Date:
    def __init__(self, year, month, date):
        self.year = year
        self.month = month
        self.date = date

    def __eq__(self, other):
        return self.year == other.year and self.month == other.month and self.date == other.date


x = Date(2022, 2, 22)
y = Date(2022, 2, 22)
ic(x == y)

16:39:20|> x == y: Stimmt

Wenn Python feststellt, dass in der selbst erstellten Klasse keine ungleiche Methode definiert ist, invertiert es die gleiche Methode als Rückgabewert von ungleich.

from icecream import ic


class Date:
    def __init__(self, year, month, date):
        self.year = year
        self.month = month
        self.date = date

    def __eq__(self, other):
        print('__eq__')
        return self.year == other.year and self.month == other.month and self.date == other.date


x = Date(2022, 2, 22)
y = Date(2022, 11, 22)
ic(x != y)

eq
16:50:37|> x != y: Stimmt

Wenn die Methode „Ungleich“ definiert ist, wird nur die Methode „Ungleich“ aufgerufen, wenn festgestellt wird, dass sie nicht gleich ist.

from icecream import ic


class Date:
    def __init__(self, year, month, date):
        self.year = year
        self.month = month
        self.date = date

    def __eq__(self, other):
        print('__eq__')
        return self.year == other.year and self.month == other.month and self.date == other.date

    def __ne__(self, other):
        print('__ne__')
        return self.year != other.year or self.month != other.month or self.date != other.date


x = Date(2022, 2, 22)
y = Date(2022, 11, 22)
ic(x != y)

ne
16:53:01|> x != y: Stimmt

Im Allgemeinen müssen wir nur eine __eq__-Methode in der selbst erstellten Klasse definieren.
In den Methoden __eq__ und __ne__ muss ein weiteres zu vergleichendes Objekt bereitgestellt werden: other, da diese beiden Methoden für den binären Vergleich verwendet werden.
Aber wenn wir beurteilen, ob x gleich y ist: x == y, beurteilen wir tatsächlich: x. eq (y). y wird als other an die __eq__-Methode von x übergeben.

4.10.3.2 gtlt

Gleich oder ungleich bedeutet, dass es eine Standardimplementierung gibt. Wenn diese nicht definiert ist, wird die Standardimplementierung anhand von is beurteilt. Wenn jedoch „größer als“ und „kleiner als“ nicht definiert sind, wird beim direkten Vergleich ein Fehler gemeldet.

from icecream import ic


class Date:
    def __init__(self, year, month, date):
        self.year = year
        self.month = month
        self.date = date

    def __eq__(self, other):
        print('__eq__')
        return self.year == other.year and self.month == other.month and self.date == other.date

    def __ne__(self, other):
        print('__ne__')
        return self.year != other.year or self.month != other.month or self.date != other.date

    def __gt__(self, other):
        if self.year > other.year:
            return True
        if self.year == other.year:
            if self.month > other.month:
                return True
            if self.month == other.month:
                return self.date > other.date


x = Date(2023, 2, 22)
y = Date(2022, 11, 22)
ic(x > y)

17:08:33|> x > y: Stimmt

Obwohl wir hier nur die Größer-als-Methode definieren, können wir zu diesem Zeitpunkt das Kleiner-als-Zeichen direkt verwenden, da Python standardmäßig festlegt, dass das Größer-als-Zeichen und das Kleiner-als-Zeichen ein Paar sind. Wenn nicht anders angegeben, bedeutet x > y y < x. Wenn festgestellt wird, dass x < y ist und es keine Kleiner-als-Methode in x gibt, wird die Größer-als-Methode in y gefunden, sodass auch eine Beurteilung erfolgen kann.

4.10.3.3 wennund

Python spekuliert nicht über kleiner oder gleich, größer oder gleich, also größer oder gleich einem Ganzen, nicht über größer oder gleich. Wenn „größer als oder gleich“ nicht definiert ist, wird ein Fehler gemeldet, wenn Sie „größer als oder gleich“ direkt zur Beurteilung verwenden, anstatt „größer als oder gleich“ aufzurufen und dann eine logische Operation „oder“ auszuführen.

from icecream import ic


class Date:
    def __init__(self, year, month, date):
        self.year = year
        self.month = month
        self.date = date

    def __ge__(self, other):
        print('__ge__')
        if self.year > other.year:
            return True
        if self.year == other.year:
            if self.month > other.month:
                return True
            if self.month == other.month:
                return self.date >= other.date
    def __le__(self, other):
        print('__le__')
        if self.year < other.year:
            return True
        if self.year == other.year:
            if self.month < other.month:
                return True
            if self.month == other.month:
                return self.date <= other.date


x = Date(2023, 2, 22)
y = Date(2022, 11, 22)
ic(x >= y)

ge
17:16:13|> x >= y: Stimmt

4.10.3.4 Hash

In Python verfügt jede benutzerdefinierte Klasse standardmäßig über eine __hash__-Methode zum Binden. Wenn die Methode __eq__ definiert ist, wird die Standardmethode __hash__ gelöscht. Diese benutzerdefinierte Klasse wird nicht mehr hashbar.
Der Grund dafür ist, dass in Python, wenn zwei Objekte gleich sind, auch die Hashwerte dieser beiden Objekte gleich sein müssen. Daher müssen wir die Methode __hash__ selbst definieren, nachdem wir die Methode __eq__ definiert haben.
Die Anforderungen an die Methode __hash__ sind:
1. Sie muss eine Ganzzahl zurückgeben
2. Bei zwei gleichen Objekten muss auch der Hash-Wert gleich sein.
Zur Auswertung verwenden Sie am besten die mit Python mitgelieferte Hash-Funktion wie folgt:

from icecream import ic


class Date:
    def __init__(self, year, month, date):
        self.year = year
        self.month = month
        self.date = date

    def __eq__(self, other):
        return self.year == other.year and self.month == other.month and self.date == other.date

    def __hash__(self):
        return hash((self.year, self.month, self.date))


x = Date(2023, 2, 22)
y = Date(2023, 2, 22)
dct = {
    
    x: 999, y: 999}
ic(dct)

17:27:37|> dct: {< main .Date object at 0x000001A6C49EBEE0>: 999}

4.10.3.5 bool

Wenn alle unsere benutzerdefinierten Objekte direkt als Beurteilungsbedingung der if-Anweisung verwendet werden, geben sie True zurück. Wenn Sie das Ergebnis eines benutzerdefinierten Objekts ändern möchten, wenn Sie boolesche Operationen ausführen, können Sie die magische Methode __bool__ verwenden.

from icecream import ic


class Date:
    def __init__(self, year, month, date):
        self.year = year
        self.month = month
        self.date = date

    def __bool__(self):
        print('bool')
        return False



x = Date(2023, 2, 22)
ic(bool(x))
if not x:
    ic(x)

bool
bool
ic| bool(x): Falsch
ic| x: < main .Date object at 0x0000026ECCC633A0>

おすすめ

転載: blog.csdn.net/crleep/article/details/132141606
おすすめ