我想为我的python对象生成一个哈希字符串,这样我就知道它是否已经更改。我尝试了hash((函数,但它总是为给定的对象返回相同的值,即使我更改了它的属性。
假设我有以下场景:
class User(object):
def __init__(self, name, address):
self.name = name
self.address = address
user = User("Anthony", "Street 1")
user.hash()
=> "21e12i24g"
user.address = "Street 2"
user.hash()
=> "85f7ff5a1"
在该示例中使用hash((函数将为两个调用返回相同的结果。
给对象一个散列函数的典型方法是向对象添加一个__hash__()
方法,该方法由内置函数hash()
调用。然后,将对象的属性元组化,并返回该集合的散列:
class User(object):
def __init__(self, name, address):
self.name = name
self.address = address
def __hash__(self):
return hash((self.name, self.address))
user = User("Anthony", "Street 1")
print(hash(user))
# 4909374541336696414
user.address = "Street 2"
print(hash(user))
# -1615107979785300685
对于不需要显式枚举对象的每个属性的更通用的解决方案,您可以动态地这样做。例如,下面将查看User
的所有属性,将它们列为较大元组中的键值元组,并获取其哈希值。如果您希望在前面或后面添加一个元素,例如self.__class__
,作为唯一性的一个因素。
class User(object):
def __init__(self, name, address):
self.name = name
self.address = address
def __hash__(self):
return hash(tuple((k, v) for k,v in vars(self).items()))
user = User("Anthony", "Street 1")
print(hash(user))
# -8646451939475098773
user.address = "Street 2"
print(hash(user))
# 8843995983070120839
需要注意的是,为了散列的目的,必须使用tuple
而不是list
、dict
或set
,因为这些类型都是可变的,因此不可散列。tuple
是不可变的,可以安全地进行散列。还要注意,这是一个python设计决策,并不一定意味着您不能使用散列设计可变对象(如User
(。