print([1, 2] == [1, 2])
print(2 > 5)
print("a" <= "b")
输出结果为:
True
False
True
在python中我们经常会比较两个数据结构是否相等,或者比较两个数据结构的大小叫做rich comparison。
rich comparison一共包含了六个操作符。
在python的内置数据结构中,比如说dict,或者list,尤其是integer、string、float,它们的rich comparison都是有良好的定义的。
然而,有时候对于我们自己写的数据结构,我们也希望利用这些比较运算符。
而比较的逻辑实现,我们就是通过魔术方法来完成的。
我们举个例子:
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)
print(x == y)
输出结果为:
False
在python中,当你没有去写一个类的比较逻辑的时候,它默认比较两个对象的是否相等的方法是会默认调用object.__eq__
方法,默认比较两个对象的地址(id),默认调用了is
。
__eq__
魔术方法__eq__
是 Python 中一个重要的魔术方法,它用于判断两个对象是否相等。
__eq__
方法默认情况下是比较两个对象的内存地址是否相等,即 id(self) == id(other)
。如果我们想让自定义的类支持比较操作,就需要自定义 __eq__
方法。
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, 2, 22)
print(x == y)
print(x != y)
输出结果为:
__eq__
True
__eq__
False
这里我们并没有定义不等于,python默认调用了__eq__
后取反。
__ne__
魔术方法__ne__
是Python的一个魔术方法,用于比较两个对象是否不相等。它是“not equal”的缩写,与__eq__
(等于)方法相对应。当使用!=
操作符时,解释器就会调用__ne__
方法来执行不相等的比较。
__ne__
方法的默认实现是返回not self == other
。因此,如果你在类中定义了__eq__
方法,那么你应该同时定义__ne__
方法,以确保比较的正确性。
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 and self.month != other.month and self.date != other.date
x = Date(2022, 2, 22)
y = Date(2022, 2, 22)
print(x == y)
print(x != y)
输出结果为:
__eq__
True
__ne__
False
这里不等于时就调用的__ne__
。
__gt__
魔术方法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)
print(x > y)
输出结果为:
Traceback (most recent call last):
File "/mnt/f/lianhaifeng_codes/djangoProject/djangoProject/example2.py", line 20, in <module>
print(x > y)
TypeError: '>' not supported between instances of 'Date' and 'Date'
__gt__
是Python中的一个魔术方法,用于实现大于(greater than)比较运算符“>”。当我们使用“>”运算符来比较两个对象时,实际上是调用了其中一个对象的__gt__
方法,这个方法返回True或False。
class Date:
def __init__(self, year, month, date):
self.year = year
self.month = month
self.date = date
def __gt__(self, other):
print("__gt__")
if self.year > other.year:
return True
if self.month > other.month:
return True
if self.month == other.month:
return self.date > other.date
x = Date(2022, 2, 22)
y = Date(2022, 2, 22)
print(x > y)
print(x < y)
输出结果为:
__gt__
False
__gt__
False
总之,__gt__
是Python中的一个魔术方法,用于实现大于比较运算符“>”。通过定义__gt__
方法,我们可以让我们的自定义对象支持“>”运算符。
尽管我们只实现了大于,但是也可以使用小于。
__lt__
魔术方法__lt__
是Python中的一个魔术方法,用于重载小于号<
的行为。该方法用于比较两个对象的大小关系,即是否小于。在Python中,如果两个对象无法比较大小,则会抛出TypeError
异常。
class Date:
def __init__(self, year, month, date):
self.year = year
self.month = month
self.date = date
def __gt__(self, other):
print("__gt__")
if self.year > other.year:
return True
if self.month > other.month:
return True
if self.month == other.month:
return self.date > other.date
def __lt__(self, other):
print("__lt__")
if self.year < other.year:
return True
if self.month < other.month:
return True
if self.month == other.month:
return self.date < other.date
x = Date(2022, 2, 22)
y = Date(2022, 2, 22)
print(x > y)
print(x < y)
输出结果为:
__gt__
False
__lt__
False
在这里我们就会怀疑了了x<y
语义上既是x小于y,又是y>x
,到底是执行__gt__
函数还是__lt__
函数了?
举个栗子:
class Date:
def __init__(self, year, month, date):
self.year = year
self.month = month
self.date = date
def __gt__(self, other):
print("__gt__")
if self.year > other.year:
return True
if self.month > other.month:
return True
if self.month == other.month:
return self.date > other.date
def __lt__(self, other):
print("__lt__")
if self.year < other.year:
return True
if self.month < other.month:
return True
if self.month == other.month:
return self.date < other.date
class NewDate(Date):
pass
x = Date(2022, 2, 22)
y = Date(2022, 2, 23)
print(x < y)
print(" ")
z = Date(2022, 2, 22)
zz = NewDate(2022, 2, 23)
print(z < zz)
输出结果为:
__lt__
True
__gt__
True
如果y是x的衍生类,优先使用y的rich comparison的函数,否者优先使用x的函数。大部分情况优先使用左边的函数。
__le__
和__ge__
魔术方法__le__
是Python中的一个特殊方法,用于实现对象之间小于等于比较运算符<=
的行为。如果在类中定义了__le__
方法,则当使用小于等于比较运算符时,Python将调用该方法来确定两个对象的大小关系。
__ge__
是Python中的一个魔术方法,用于实现大于等于操作符(>=
)的行为。该方法接收两个参数:self
和other
,其中self
表示类的实例本身,other
表示与之比较的另一个对象。该方法应该返回一个布尔值,表示两个对象的大小关系是否满足大于等于的条件。
class Date(object):
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.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.month < other.month:
return True
if self.month == other.month:
return self.date < other.date
x = Date(2022, 2, 22)
y = Date(2022, 2, 23)
print(x <= y)
print(x >= y)
输出结果为:
__le__
True
__ge__
False
__hash__
魔术方法在 Python 中,__hash__()
函数是一个魔术方法,用于返回对象的哈希值。哈希值是一个整数,用于在字典查找中快速比较两个对象是否相等。在使用字典、集合等可哈希类型时,需要实现这个方法。
__hash__()
函数应该返回一个整数。如果两个对象相等,则它们的哈希值必须相同,反之则不一定成立。
实现 __hash__()
函数通常要和 __eq__()
函数配合使用,保证对象的哈希值与相等性有关。例如,如果两个对象相等,则它们的哈希值也相等,可以实现如下:
class MyClass:
def __init__(self, x):
self.x = x
def __eq__(self, other):
if not isinstance(other, MyClass):
return NotImplemented
return self.x == other.x
def __hash__(self):
return hash(self.x)
在这个例子中,我们定义了一个自定义类 MyClass
,它包含一个属性 x
。我们实现了 __eq__()
方法,以便在比较对象时使用,如果两个对象的 x
属性相等,则它们相等。我们还实现了 __hash__()
方法,它返回对象的哈希值,这里使用 hash()
内置函数对对象的 x
属性进行哈希。
当我们使用这个类创建对象时,我们可以将它们添加到字典中,并使用 __eq__()
方法进行比较,例如:
a = MyClass(1)
b = MyClass(1)
c = MyClass(2)
print(a == b) # True
print(a == c) # False
d = {a: 'value'}
print(d[b]) # 'value'
在上面的例子中,我们创建了三个对象 a
、b
、c
,其中 a
和 b
的 x
属性相等,而 c
的 x
属性不同。我们可以使用 ==
运算符比较它们的相等性,也可以将它们添加到字典 d
中,使用哈希值进行比较,最终输出 'value'
。
总之,__hash__()
函数在 Python 中是非常重要的,它为我们提供了一种快速比较对象是否相等的方法,使我们能够在使用字典、集合等可哈希类型时,快速查找对象。
__bool__
魔术方法__bool__
是Python中的一个魔术方法,也称为特殊方法或者魔法方法,它是在类中实现用于定义实例转换为布尔值的方式。当Python需要将实例转换为布尔值(例如,在条件语句中使用)时,会调用该方法。
__bool__
方法应该返回一个布尔值True或False,来表示对象是否被视为“真”或“假”。如果该方法没有被定义,则默认返回True,因为Python中的所有对象都被视为“真”,除非它们明确地定义为“假”。
下面是一个简单的例子,展示了如何在类中定义__bool__
方法:
class MyClass:
def __init__(self, num):
self.num = num
def __bool__(self):
return self.num > 0
在上面的例子中,MyClass
类的__bool__
方法返回self.num > 0
的结果,这表示当num
大于0时,该实例被视为“真”,否则被视为“假”。在实际使用中,可以像下面这样使用这个类:
>>> x = MyClass(5)
>>> if x:
... print("x is true")
...
x is true
>>> y = MyClass(0)
>>> if not y:
... print("y is false")
...
y is false
在上面的例子中,我们创建了两个MyClass
实例,一个具有正数的num
属性,另一个具有零值的num
属性。我们使用条件语句检查这些实例,以确定它们是否被视为“真”或“假”。