Pao*_*ila 8 python hash set python-3.x
我正在开发一个基于代理的模型,其中我使用不同类型的代理类,这些类的实例被分配给不同类型的对象,例如学校、公司、家庭等。我遇到的问题是我在调试时无法强制执行运行的再现性,由于模型的复杂性,这使得任务变得非常困难。经过长时间的调查,我意识到问题与集合的顺序有关(当然应用了内置的随机和 numpy 随机种子)。即使我设置了 PYHTONHASHSEED=0,我也观察到每次运行时集合的顺序是随机的。当代理移动时,这使得我的模型的每次运行都不同。
当然,我知道套装并不意味着有订单。当从对象中移除代理时,我想使用它们使模型尽可能轻巧和快速。我希望它们的行为是随机的,除非我需要调试引发异常的特定运行。
我添加了以下代码,以便可以验证我的声明。在启动代码之前,我总是通过导出从命令行设置 PYTHONHASHSEED。我从代码打印 PYTHONHASHSEED 值以检查该值是否确实已更新
import os
import random
import numpy as np
print('PYTHON HASH SEED IS', os.environ['PYTHONHASHSEED'])
random.seed(1)
np.random.seed(2)
class S:
def __init__(self, a, b):
self.a = a
self.b = b
def __repr__(self):
return "".join([type(self).__name__, "_{0.a!r}_",
"School", "_{0.b!r}" ]).format(self)
list1 = np.random.randint(1, 100,size=40)
list2 = np.random.randint(1, 10,size=40)
d1 = dict()
s1 = set()
d1['students'] = s1
# assign students to d1
for s_id, sch_id in zip(list1, list2):
d1['students'].add(S(s_id, sch_id))
print(s1)
Run Code Online (Sandbox Code Playgroud)
奇怪的是,如果我使用整数作为集合成员而不是类实例,则无法检测到随机性。问题是否与集合成员是类实例这一事实有关?为什么 ?
当然,我可以重塑代理分配给模型对象的方式,并用列表替换集合,但如果可能的话,我想了解这个问题。我使用的版本是python 3.5.4
您存储的(类型S
)对象来自没有覆盖__eq__
和的类__hash__
,因此它们使用默认实现,即基于对象标识:
用户定义的类默认有
__eq__()
和__hash__()
方法;与它们相比,所有对象都比较不相等(除了它们自己)并x.__hash__()
返回一个适当的值,以便同时x == y
暗示x is y
和hash(x) == hash(y)
。
对象标识(作为 CPython 的一个实现细节)等同于分配对象的内存地址(原始指针值),并且分配器将在每次运行时返回不同的地址,因此每次的排序都会不同。int
s 没有这个问题,因为它们具有基于非身份的平等和散列;它们基于值而不是身份进行散列,因此精确的内存地址无关紧要。
要使用固定种子为您的自定义类获得一致的排序,您需要定义特殊的相等和散列方法,例如:
def __hash__(self):
return hash((self.a, self.b))
def __eq__(self, other):
if not isinstance(other, S):
return NotImplemented
return self.a == other.a and self.b == other.b
Run Code Online (Sandbox Code Playgroud)