4.10.3 Comparación
En Python, a menudo comparamos la igualdad de dos estructuras de datos o comparamos tamaños. Para las estructuras de datos integradas de Python, la comparación de estas estructuras de datos está bien definida.
Las estructuras de datos escritas por los propios usuarios a veces necesitan compararse entre sí. La implementación lógica de la comparación se realiza a través de métodos mágicos.
En Python, si no se escribe una lógica de comparación en la clase personalizada, se usa para la comparación de forma predeterminada.
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: Falso
4.10.3.1 eq、ne
"==" llamará a este método al juzgar si dos objetos son iguales.
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: Verdadero
Si Python encuentra que no hay un método no igual definido en la clase autoconstruida, invertirá el método igual como el valor de retorno de no igual.
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)
ecuación
16:50:37|> x != y: Verdadero
Si se define el método no igual, solo se llamará al método no igual cuando se considere que no es igual a.
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: Verdadero
En general, solo necesitamos definir un método __eq__ en la clase autoconstruida.
En los métodos __eq__ y __ne__, es necesario proporcionar otro objeto para comparar: otro, porque estos dos métodos se utilizan para la comparación binaria.
Pero cuando juzgamos si x es igual a y: x == y, en realidad estamos juzgando: x.eq ( y). y se pasará como otro al método __eq__ de x.
4.10.3.2 gt , lt
Igual a, no igual a tener una implementación predeterminada, si no se define, el valor predeterminado se juzgará por sí. Sin embargo, si mayor que y menor que no están definidos, la comparación directa informará un error.
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: Verdadero
Aunque aquí solo definimos el método mayor que, podemos usar directamente el signo menor que en este momento, porque Python tiene por defecto que el signo mayor que y el signo menor que son un par. Cuando no se especifica lo contrario, x > y significa y < x. Si se juzga que x < y, si no hay menos que método en x, encontrará el mayor que método en y, de modo que también se pueda hacer el juicio.
4.10.3.3 si、y
Python no especula sobre menor o igual que, mayor o igual que, es decir, mayor o igual que un todo, no mayor o igual que. Cuando mayor o igual no está definido, se informará un error si usa directamente mayor o igual para juzgar, en lugar de llamar a mayor o igual y luego realizar una operación lógica o.
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: Verdadero
4.10.3.4 hash
En Python, cada clase personalizada tendrá un método __hash__ para enlazar de forma predeterminada. Si se define el método __eq__, se eliminará el método __hash__ predeterminado. Esta clase personalizada se volverá imposible de modificar.
La razón es que, en Python, si dos objetos son iguales, entonces los valores hash de esos dos objetos también deben ser iguales. Por lo tanto, debemos definir el método __hash__ nosotros mismos después de definir el método __eq__.
Los requisitos del método __hash__ son:
1. Debe devolver un número entero
2. Para dos objetos iguales, el valor hash también debe ser el mismo.
Lo mejor es usar la función hash que viene con Python para la evaluación, de la siguiente manera:
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: {< objeto principal .Date en 0x000001A6C49EBEE0>: 999}
4.10.3.5 booleano
Para todos nuestros objetos personalizados, si se usan directamente como condición de juicio de la instrucción if, devolverán True. Si desea cambiar el resultado de un objeto personalizado al realizar operaciones booleanas, puede utilizar el método mágico __bool__.
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): Falso
ic| x: < objeto principal .Date en 0x0000026ECCC633A0>