为什么dict1.items()<= dict2.items()和dict1.viewitems()<= dict2.viewitems()返回不同的结果?

时间:2019-10-08 17:57:06

标签: python python-3.x python-2.7 dictionary

当将两个字典作为列表进行比较时,为什么.items()返回与.viewitems()不同的结果令我感到困惑。

# python 2.7
d1 = {'1': '10', '2': '20'}  # two key-value pairs
d2 = {'3': '30', '4': '40', '5': '50'}  # three key-value pairs
print d1 <= d2  # True
print d1.items() <= d2.items()  # True
print d1.viewitems() <= d2.viewitems()  # False
print d1.items()  # [('1', '10'), ('2', '20')]
print d1.viewitems()  # dict_items([('1', '10'), ('2', '20')])

似乎.items()和.viewitems()之间的主要区别是 .items()返回列表,而viewitems()返回dict_items。

在比较字典之间的大小时,是否建议仅使用d1 <= d2而不是视图项或项目?

另外,如何使它与Python 3兼容?

3 个答案:

答案 0 :(得分:5)

d1 <= d2  # True

这很复杂。这是实现细节。请参见What do comparison operators do on dictionaries? TL; DR:较短的字典总是比Python 2.x中的较长字典小,但是字典在Python 3.x中根本无法排序。

d1.items() <= d2.items()  # True

这是列表的lexicographical比较。 True的结果是可靠的,因为d1中的每个键小于d2中的任何键。为了使该代码具有交叉兼容性,您必须显式转换为列表。

d1.viewitems() <= d2.viewitems()  # False

这是类似子集的检查。该False结果是可靠的,因为d1不是d2的“下标”。要使此代码交叉兼容,请使用six.viewitems或类似的代码。

  

在比较字典之间的大小时,是否建议仅使用d1 <= d2而不是视图项或项目?

都不使用len(d1) <= len(d2)比较字典之间的大小。

答案 1 :(得分:1)

我在这里回答了类似的问题:Inconsistent behaviour between dict.values() and dict.keys() equality in Python 3.x and Python 2.7

要注意的关键是dict.viewitems()Set-like对象。这意味着当您进行d1.viewitems() <= d2.viewitems()时,您正在比较检查d1.viewitems()是否是d2.viewitems()子集,而不是您期望的长度比较。请参阅此处的文档:https://docs.python.org/2.7/library/sets.html#set-objects

Operation         Equivalent  Result
s.issubset(t)     s <= t      test whether every element in s is in t
s.issuperset(t)   s >= t      test whether every element in t is in s

注意:,因为dict.viewitem()collections.Set对象,所以它没有.issubset.issuperset这样的方法,例如set会。

观察以下内容:

>>> d1 = {'a': 0}
>>> d2 = {'a': 1}
>>> d3 = {'a': 0, 'b': 1}
>>> d1.viewitems() <= d3.viewitems()
True     # because [('a', 0)] is a subset of [('a', 0), ('b', 1)]
>>> d2.viewitems() <= d3.viewitems()
False    # because [('a', 1)] is not a subset of [('a', 0), ('b', 1)]

不过,要回答您的问题-正如其他人所提到的,要比较大小,请改用len(d1) <= len(d2)

答案 2 :(得分:0)

您声明的目的是比较字典的大小……您根本没有做过。为此,您需要使用len

您所做的是比较两种截然不同类型的项目。 items返回一个元组列表,可以通过众所周知的算法轻松比较它们:以给定顺序检查元素的相对值。我们大多数人都熟悉元组比较。

但是,dict_view是动态视图对象,不是简单的值列表。您正在比较一个更复杂的对象,而不仅仅是运行明显的值列表。仅仅是凡人,排序和比较的定义是不容易看到的。