尝试在Python中对深层嵌套结构排序时出现不一致的行为

尝试在Python中对深层嵌套结构排序时出现不一致的行为,python,python-2.7,python-3.x,sorting,nested,Python,Python 2.7,Python 3.x,Sorting,Nested,我试图在Python3中对深层嵌套列表或字典结构进行排序,其中内置的排序函数无法比较不同的对象类型,就像Python2一样。我得到了我的解决方案,大部分时间我都得到了预期的结果,但是在我的一个测试中,我有不一致的行为,试图对字典对象进行深层排序。有时当我运行下面的代码时,断言通过,有时它无法对内部列表字典项进行排序: OrderedDict([(‘旅程’,[None,OrderedDict([(‘id’,1),(‘乘客’,[1,2]),(‘价格’,100)]),OrderedDict([(‘id

我试图在Python3中对深层嵌套列表或字典结构进行排序,其中内置的排序函数无法比较不同的对象类型,就像Python2一样。我得到了我的解决方案,大部分时间我都得到了预期的结果,但是在我的一个测试中,我有不一致的行为,试图对字典对象进行深层排序。有时当我运行下面的代码时,断言通过,有时它无法对内部列表字典项进行排序:

OrderedDict([(‘旅程’,[None,OrderedDict([(‘id’,1),(‘乘客’,[1,2]),(‘价格’,100)]),OrderedDict([(‘id’,3),(‘乘客’,[1,2]),(‘价格’,200)],OrderedDict([(‘id’,2),(‘乘客’,[3,4]),(‘价格’,150)])
回溯(最近一次呼叫最后一次):
文件“solution.py”,第90行,在
assert new_lst==结果
断言错误
我一直在看我的代码,但我无法找出哪里出了问题,因为它看起来像是处理进程或线程时可能发生的行为,但事实并非如此。如果您想知道这仍然是移植Python2.x代码和Python3.x的草案代码,那么在尝试对不同内置数据类型的深度嵌套结构进行排序时,“排序”函数不兼容问题就起了作用。我使用访问者模式递归遍历所有节点,并使用预定义规则(
self.data\u weights
)对不同的内置数据类型进行排序

我现在陷入了困境,非常感谢您帮助我找出下面代码的错误

我正在执行以下代码:

Python 3.4.3(默认值,2016年11月17日,01:08:31) linux上的[GCC 4.8.4]

更新:我的测试与Python 3.6.2一致通过(请参见下面的Python版本)。我所经历的奇怪行为发生在Python 3.4.3中。有什么想法吗

Python 3.6.2(默认值,2017年7月20日,08:43:29) [GCC 4.9.4]在linux上


我不确定是什么导致了断言失败:我还没有找到有时可能是错误的具体比较。但我认为这可能是因为这句话:

v.sort(key=lambda x: str(x))
使用
str
值的
dict
对数据进行排序

在任何情况下,这些症状向我表明,它是由Python按照字典迭代顺序指定的非确定性造成的

在Python2.7中,如果您在字典上进行迭代(例如,通过调用
str
),那么您将获得任意顺序。但是,只要以相同的方式构造相同的字典,并且插入和删除的顺序相同,那么这种顺序就始终是相同的

对于蟒蛇3.3到3.5,这不再是事实。由于默认情况下引入了散列随机化,Python的连续调用可能会改变字典的顺序,即使它是以相同的方式构造的。在单个解释器的生命周期内,顺序是一致的,但在下次运行时可能会改变

在Python3.6中,这种情况再次发生了变化。词典现在保留了它们的构造顺序,并且迭代总是按照这个顺序进行


因此,我怀疑您的测试对字典的迭代顺序很敏感,这会导致您看到不一致的结果。

我不确定是什么导致您的断言失败:我没有找到有时可能是错误的特定比较。但我认为这可能是因为这句话:

v.sort(key=lambda x: str(x))
使用
str
值的
dict
对数据进行排序

在任何情况下,这些症状向我表明,它是由Python按照字典迭代顺序指定的非确定性造成的

在Python2.7中,如果您在字典上进行迭代(例如,通过调用
str
),那么您将获得任意顺序。但是,只要以相同的方式构造相同的字典,并且插入和删除的顺序相同,那么这种顺序就始终是相同的

对于蟒蛇3.3到3.5,这不再是事实。由于默认情况下引入了散列随机化,Python的连续调用可能会改变字典的顺序,即使它是以相同的方式构造的。在单个解释器的生命周期内,顺序是一致的,但在下次运行时可能会改变

在Python3.6中,这种情况再次发生了变化。词典现在保留了它们的构造顺序,并且迭代总是按照这个顺序进行


因此,我怀疑您的测试对字典的迭代顺序很敏感,这会导致您看到不一致的结果。

在对字典进行排序后,我正在将字典转换为有序字典,这可能是重复的,但我不是在比较OrderedDictionary,所以我相信这是不一样的。问题可能是您无法使用
==
运算符将列表与OrderedDict对象进行比较,但我只是在猜测。assert语句中的==运算符是在比较OrderedDict与OrderedDict对象。我有使用self.assertEqual进行相同比较的单元测试,我有相同的行为-有时通过,有时不通过。在
assert
之前,检查每个
orderedict
的内容:
打印新的\lst;打印所需的
,比较,它们不匹配可能的副本,我正在将字典排序后转换为OrderedDictionary,但我没有比较OrderedDictionary,因此我认为这是不同的。问题可能是您无法使用
=
运算符将列表与OrderedDictionary对象进行比较,但我只是在猜测。assert语句中的==运算符正在比较OrderedICT和OrderedICT对象。我有使用self.assertEqual进行相同比较的单元测试,我有相同的行为——有时通过,有时通过