Python 如何在没有顺序的情况下使用dict断言两个列表?

Python 如何在没有顺序的情况下使用dict断言两个列表?,python,unit-testing,python-3.x,Python,Unit Testing,Python 3.x,各位。我最近从Python2切换到3.5.1,有一个断言函数,我无法重写 def assertEqualUnordered(self, data1, data2): """ compare that data are similar i.e.: [d1, d2] == [d2, d1] or {'a': [d1, d2]} == {'a': [d2, d1]} or [{'a': [d1, d2]}, {'b': [d3, d4]}

各位。我最近从Python2切换到3.5.1,有一个断言函数,我无法重写

def assertEqualUnordered(self, data1, data2):
    """
    compare that data are similar
    i.e.:
    [d1, d2] == [d2, d1]
    or
    {'a': [d1, d2]} == {'a': [d2, d1]}
    or
    [{'a': [d1, d2]}, {'b': [d3, d4]}] == [{'b': [d4, d3]}, {'a': [d2, d1]}]
    """
    if isinstance(data1, list) or isinstance(data1, tuple):
        self.assertEqual(len(data1), len(data2))
        for d1, d2 in zip(sorted(data1), sorted(data2)):
            self.assertEqualUnordered(d1, d2)
    elif isinstance(data1, dict):
        data1_keys = sorted(data1.keys())
        data2_keys = sorted(data2.keys())
        self.assertListEqual(data1_keys, data2_keys)
        for key in data1_keys:
            self.assertEqualUnordered(data1[key], data2[key])
    else:
        self.assertEqual(data1, data2)
一般来说,此代码正常工作,但如果d1和d2是DICT,则我得到:

TypeError:无序类型:dict()

我如何重写它才能在py3k中工作

编辑1: 简化代码示例:

def assertEqualUnordered(data1, data2):
    assert len(data1) == len(data2)
    for d1, d2 in zip(sorted(data1), sorted(data2)):
        assert d1 == d2

data1 = [{'a': 'a'}, {'b': 'b'}]
data2 = [{'b': 'b'}, {'a': 'a'}]
assertEqualUnordered(data1, data2)

我不确定这是否是最简单的方法,但您可以通过恢复Python3删除的
cmp
函数来实现排序。大致如下:

def cmp(lhs, rhs):
    try:
        if lhs == rhs:
            return 0
        elif lhs < rhs:
            return -1
        else:
            return 1
    except TypeError:
        if isinstance(lhs, dict) and isinstance(rhs, dict):
            return dict_cmp(lhs, rhs)
        raise
def cmp(左侧、右侧):
尝试:
如果lhs==rhs:
返回0
elif lhs
有关
dict\u cmp
的实现,请参阅

一旦有了
cmp
函数,就可以进行
排序(data1,key=functools.cmp_to_key(cmp))

这仍然不完整,因为我还没有尝试讨论混合类型比较,例如,如果您将
[{'a':'b'},['a']]
作为对象之一传入,就会出现混合类型比较。但希望我已经提供了一个前进的方向

另一种选择是回到
O(n^2)
算法,这实际上与Python3的观点一致,即字典没有顺序。不要对列表进行排序,然后比较它们是否相等,而是依次选择左侧的每个项目,并在右侧搜索与其相等的项目(删除以确保两侧的计数相同,因为您不希望错误地声称
[x,x,y]
等于
[x,y,y]


顺便说一句,答案并不需要,但我注意到您当前的代码会说
['a','b']
{'a':'foo','b':'bar'}
无序相等,但前提是列表在左侧,词典在右侧。如果您以另一种方式传递它们,那么当代码试图调用列表上的
keys()
时,您会得到一个异常。这可能需要寻址,具体取决于您计划传入的内容;-)

你能不能简化一下,更深入地了解你所看到的失败?我假设这与keys()返回视图而不是列表有关。另外,您可以包含完整的堆栈跟踪吗?显示引发异常的代码:此代码不使用
@jgritty simplify代码example@SteveJessop但是有一个分类code@vanadium23:是的,如果您显示了异常堆栈跟踪,那么我们可以看到异常是否来自对
排序的调用,如果是,则是哪一个:-)我认为您添加的示例涵盖了它,谢谢,因为现在只有一个地方会出错!