【发布时间】:2017-06-27 04:26:03
【问题描述】:
我遇到了这个:
>>> d1 = {"john":40, "peter":45}
>>> d2 = {"john":466, "peter":45}
>>> d1 > d2
False
比较两个dict时比较运算符做了什么,它如何输出False?
【问题讨论】:
标签: python python-2.7 dictionary
我遇到了这个:
>>> d1 = {"john":40, "peter":45}
>>> d2 = {"john":466, "peter":45}
>>> d1 > d2
False
比较两个dict时比较运算符做了什么,它如何输出False?
【问题讨论】:
标签: python python-2.7 dictionary
由于这些 dicts 的长度相等,我们找到对应值不相等的最小键,即'john'。然后根据该键的值比较字典。
演示:
>>> d1 = {"john":40, "peter":45}
>>> d2 = {"john":466, "peter":45}
>>> d1 < d2
True
>>> d2['john'] = 39
>>> d1 < d2
False
这个基本理念自 20 多年前的Guido's commit 以来基本上没有改变:
$ git show a0a69b8
commit a0a69b8b429f3d4c91f1c432247cfda017505976
Author: Guido van Rossum <guido@python.org>
Date: Thu Dec 5 21:55:55 1996 +0000
Experimental new implementation of dictionary comparison. This
defines that a shorter dictionary is always smaller than a longer one.
For dictionaries of the same size, the smallest differing element
determines the outcome (which yields the same results as before,
without explicit sorting).
它没有记录,并且字典比较代码在 Python 3 中被删除,所以我不会依赖它来做任何重要的事情。相关的 CPython 源代码是 here。
有趣的事实:显然,在旧版本的 Python 中,一些 dict 比较可能会导致运行时崩溃,甚至可能会导致 cause Windows 98 to reboot。呵呵。
【讨论】:
字典和集合一样,不会在其元素上保持明确的顺序。 此外,子集的概念通常对字典没有意义,因此 这 听写 类不支持运算符,例如
<.字典支持这个概念 等价的,与 d1 == d2 如果两个字典包含相同的键集 值对。
所以你可以做的是,
d1 == d2 #d1 is equivalent to d2
d1 != d2 #d1 is not equivalent to d2
但是你不能这样做> < >= <=
这是在 python 3 中。
>>> a
{1: '1', 2: '2'}
>>> b
{1: '1', 2: '2'}
>>> a==b
True
>>> a<b
Traceback (most recent call last):
File "<pyshell#31>", line 1, in <module>
a<b
TypeError: unorderable types: dict() < dict()
>>> a>b
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
a>b
TypeError: unorderable types: dict() > dict()
>>>
不过在 python 2 中看看这个,
>>> a = {2:2}
>>> b = {2:2}
>>> a==b
True
>>> a<b
False
>>> a>b
False
但是当key 相同而value 不同时
>>> a={3:1}
>>> b={3:2}
>>> a<b
True
>>> a>b
False
同样,如果value 相同,
>>> a={3:0}
>>> b={3:0}
>>> a==b
True
>>> a<b
False
>>> a>b
False
但是当第一个 dict 的值更大时请注意这一点
>>> a={3:200}
>>> b={3:10}
>>> a<b
False
>>> a>b
True
到目前为止,我们有相同的 key 不同的 values 现在让我们改变它,
现在相同的值不同的键
>>> a={2:10}
>>> b={3:10}
>>> a<b
True
>>> a>b
False
>>>
>>> a={10:10}
>>> b={1:10}
>>> a<b
False
>>> a>b
True
你能从中得到什么,Python 2 中的任何一个键都会被检查,如果相同,只有那么,值才会被检查。现在让我们有不同的键,不同的值,
>>> a={10:10}
>>> b={1:100}
>>> a<b
False
>>> a>b
True
啊哈!在这种情况下,您可以推断key 是要检查的第一件事,如果它们相同,则将检查值。现在假设我们的字典中有不止一对key:value?
>>> a={10:10,1:10}
>>> b={10:10,2:10}
>>> a<b
True
>>> a>b
False
>>> a={10:10,200:10}
>>> b={10:10,1:10}
>>> a<b
False
>>> a>b
True
意思是。检查每个key,然后检查key 是否相同。啊,但是密钥检查是如何工作的?看看dict_compare source code
注意: cmp() 方法返回两个数之差的符号:如果 x y 则返回 1
所以基本上会发生什么是比较 dicts A 和 B,首先比较长度(等于没问题)。如果它们不相等,则返回 cmp(len(A), len(B))。
接下来,在 A 中找到键 akey,它是
akey not in B or
A[akey] != B[akey] -->(仅当 B 中存在 akey 时才会发生这种情况。
(如果没有这样的键,则dicts是相等的。)
另外(必须)找到 B 中的最小键 bkey
bkey not in A
或A[bkey] != B[bkey] -->(仅当 B 中存在 bkey 时才会发生这种情况)。
如果 akey != bkey,则返回 cmp(akey, bkey)。否则返回 cmp(A[akey], B[bkey])
>>> a={10:10,200:10}
>>> b={10:10,1:10}
>>> a<b
False
>>> a>b
True
>>> cmp(200,1)
1
>>> cmp(1,200)
-1
所以A 中而不是B 中的最小键是200 类似地1 在A 中。
现在python内部会根据上面给出的算法比较它们,所以cmp(200,1)会在a>b完成时计算出来。否则 cmp(1,200) 如果 a<b 完成。
但这已从 python 3 中完全删除。这在 python 3 中不起作用。
【讨论】:
>>> d2>d1
True
>>> d3 = {"john":40, "peter":45}
>>> d1>=d3
True
正如您在上面看到的,通过键对字典进行比较。这些是相等的;
>>> res = []
>>> for key1,val1 in d1.iteritems():
... res.append(val1 >d2[key1] )
>>> res
[False, False]
>>> all(res)
False
>>> d1 > d2
False
【讨论】: