如何从Python对象生成哈希以进行版本控制



我想为我的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而不是listdictset,因为这些类型都是可变的,因此不可散列。tuple是不可变的,可以安全地进行散列。还要注意,这是一个python设计决策,并不一定意味着不能使用散列设计可变对象(如User(。

最新更新