【问题标题】:What do comparison operators do on dictionaries?比较运算符对字典有什么作用?
【发布时间】: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


    【解决方案1】:

    由于这些 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。呵呵。

    【讨论】:

      【解决方案2】:

      字典和集合一样,不会在其元素上保持明确的顺序。 此外,子集的概念通常对字典没有意义,因此 这 听写 类不支持运算符,例如 &lt; .字典支持这个概念 等价的,与 d1 == d2 如果两个字典包含相同的键集 值对。

      所以你可以做的是,

      d1 == d2  #d1 is equivalent to d2
      d1 != d2  #d1 is not equivalent to d2
      

      但是你不能这样做&gt; &lt; &gt;= &lt;=

      这是在 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 AA[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 类似地1A 中。

      现在python内部会根据上面给出的算法比较它们,所以cmp(200,1)会在a&gt;b完成时计算出来。否则 cmp(1,200) 如果 a&lt;b 完成。

      但这已从 python 3 中完全删除。这在 python 3 中不起作用。

      【讨论】:

        【解决方案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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-09-23
          • 2015-07-03
          • 1970-01-01
          • 1970-01-01
          • 2020-12-05
          • 1970-01-01
          • 1970-01-01
          • 2013-10-20
          相关资源
          最近更新 更多