Class 自定义 __eq__ 作为哈希比较
Class Custom __eq__ as Comparison of Hashes
考虑自定义 class:
class MyObject:
def __init__(self, a, b):
self.a = a
self.b = b
def __hash__(self):
return hash((self.a, self.b))
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.__hash__() == other.__hash__()
让相等性依赖于散列是个坏主意吗?这似乎是一种比零碎地检查每对属性以获得更多属性 ala
更优雅和可读的机制
self.a == other.a and self.b == other.b and ... self.n == other.n
或使用 getattr 和列表进行更动态的检查(是否有更好的方法来比较大量的属性对?)
内置散列函数返回的散列大小是否不够大,在相对较大的数据集中不可靠?
是的,这是个坏主意。哈希值不是唯一的,具有相同哈希值的对象不保证实际上也相等:
>>> (-1, 0) == (-2, 0)
False
>>> hash((-1, 0)) == hash((-2, 0))
True
散列并不意味着是唯一的;它们是一种在有限大小 hash table 中快速选择插槽的方法,以促进 O(1) 字典查找,并且 允许和预期的冲突 .
是的,Python 要求相等的对象应具有相等的哈希值,但这并不意味着关系可以颠倒。
我只是比较元组:
def __eq__(self, other):
return (self.a, self.b) == (other.a, other.b)
如果您正在编写大量 数据 classes,简单的 classes 都需要相等性测试和散列等,请使用 dataclasses
module (Python 3.7 or up, or use a backport):
from dataclasses import dataclass
@dataclass(frozen=True)
class MyObject:
a: int
b: int
上面的 class 现在带有 __hash__
和 __equals__
方法:
>>> MyObject(-1, 0) == MyObject(-2, 0)
False
>>> hash(MyObject(-1, 0)) == hash(MyObject(-2, 0))
True
>>> MyObject(42, 12345) == MyObject(42, 12345)
True
考虑自定义 class:
class MyObject:
def __init__(self, a, b):
self.a = a
self.b = b
def __hash__(self):
return hash((self.a, self.b))
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.__hash__() == other.__hash__()
让相等性依赖于散列是个坏主意吗?这似乎是一种比零碎地检查每对属性以获得更多属性 ala
更优雅和可读的机制self.a == other.a and self.b == other.b and ... self.n == other.n
或使用 getattr 和列表进行更动态的检查(是否有更好的方法来比较大量的属性对?)
内置散列函数返回的散列大小是否不够大,在相对较大的数据集中不可靠?
是的,这是个坏主意。哈希值不是唯一的,具有相同哈希值的对象不保证实际上也相等:
>>> (-1, 0) == (-2, 0)
False
>>> hash((-1, 0)) == hash((-2, 0))
True
散列并不意味着是唯一的;它们是一种在有限大小 hash table 中快速选择插槽的方法,以促进 O(1) 字典查找,并且 允许和预期的冲突 .
是的,Python 要求相等的对象应具有相等的哈希值,但这并不意味着关系可以颠倒。
我只是比较元组:
def __eq__(self, other):
return (self.a, self.b) == (other.a, other.b)
如果您正在编写大量 数据 classes,简单的 classes 都需要相等性测试和散列等,请使用 dataclasses
module (Python 3.7 or up, or use a backport):
from dataclasses import dataclass
@dataclass(frozen=True)
class MyObject:
a: int
b: int
上面的 class 现在带有 __hash__
和 __equals__
方法:
>>> MyObject(-1, 0) == MyObject(-2, 0)
False
>>> hash(MyObject(-1, 0)) == hash(MyObject(-2, 0))
True
>>> MyObject(42, 12345) == MyObject(42, 12345)
True