Ale*_*dre 50 python dictionary ordereddictionary python-3.x
使用Python 3:
>>> from collections import OrderedDict
>>> d1 = OrderedDict([('foo', 'bar')])
>>> d2 = OrderedDict([('foo', 'bar')])
Run Code Online (Sandbox Code Playgroud)
我想检查是否平等:
>>> d1 == d2
True
>>> d1.keys() == d2.keys()
True
Run Code Online (Sandbox Code Playgroud)
但:
>>> d1.values() == d2.values()
False
Run Code Online (Sandbox Code Playgroud)
你知道为什么价值观不平等吗?
我用Python 3.4和3.5进行了测试.
在这个问题之后,我发布了Python-Ideas邮件列表以获得更多详细信息:
https://mail.python.org/pipermail/python-ideas/2015-December/037472.html
bru*_*ers 41
在Python 3,dict.keys()并dict.values()退回特殊迭代类-分别为collections.abc.KeysView和collections.abc.ValuesView.第一个继承它的__eq__方法set,第二个使用默认object.__eq__测试对象标识.
Big*_*her 20
在python3,d1.values()并且d2.values()是collections.abc.ValuesView对象:
>>> d1.values()
ValuesView(OrderedDict([('foo', 'bar')]))
Run Code Online (Sandbox Code Playgroud)
不要将它们作为对象进行比较,将它们转换为列表然后进行比较:
>>> list(d1.values()) == list(d2.values())
True
Run Code Online (Sandbox Code Playgroud)
调查为什么它用于比较_collections_abc.pyCPython中的键,KeysView是继承Set而ValuesView不是:
class KeysView(MappingView, Set):
class ValuesView(MappingView):
Run Code Online (Sandbox Code Playgroud)
寻找__eq__in ValuesView及其父母:
MappingView ==> Sized ==> ABCMeta ==> type ==> object.
__eq__仅在实现中object而不是被覆盖.
另一方面,直接KeysView继承.__eq__Set
不幸的是,当前的两个答案都没有解决为什么这样做,而是集中在如何做到这一点上。该邮件列表讨论非常了不起,所以我总结一下:
对于odict.keys/ dict.keys和odict.items/ dict.items:
odict.keys(的(的子类dict.keys)支持比较),因为它符合collections.abc.Set(是一个类似集合的对象)。这可能是由于以下事实:keys保证字典内部(有序或无序)是唯一且可哈希的。odict.items(的子类dict.items)也出于相同的原因支持比较.keys。itemsview允许这样做,因为如果items中的一个(特别是表示该值的第二个元素)不可哈希,则会引发适当的错误,但可以保证唯一性,但是(由于keys唯一):
>>> od = OrderedDict({'a': []})
>>> set() & od.items()
TypeErrorTraceback (most recent call last)
<ipython-input-41-a5ec053d0eda> in <module>()
----> 1 set() & od.items()
TypeError: unhashable type: 'list'
Run Code Online (Sandbox Code Playgroud)
对于这两个视图keys,items比较使用一个称为all_contained_in(非常易读)的简单函数,该函数使用objects __contain__方法检查所涉及视图中元素的成员资格。
现在,关于odict.values/ dict.values:
如前所述,odict.values([shocker]的子类dict.values)不像集合对象那样进行比较。这是因为valuesa的valuesview不能表示为集合,原因有两个:
正如@ user2357112和@abarnett在邮件列表中的注释中所述,odict.values/ dict.values是多集,是集的泛化,允许其元素的多个实例。尝试比较它们并不比比较简单,keys或者items由于固有的重复,排序以及您可能需要考虑与这些值相对应的键这一事实。应该dict_values看起来像这样:
>>> {1:1, 2:1, 3:2}.values()
dict_values([1, 1, 2])
>>> {1:1, 2:1, 10:2}.values()
dict_values([1, 1, 2])
Run Code Online (Sandbox Code Playgroud)
即使对应于键的值不一样,实际上是相等的吗?也许?也许不吧?这两种方法都不是直接的,并且会导致不可避免的混乱。
但是要指出的是,将它们与keys和进行比较并不是很items容易的,总之,还有@abarnett在邮件列表上的另一条评论:
如果您正在考虑尽管没有标准多集类型或ABC的定义,但我们仍可以定义多集应执行的操作并将其应用于值视图,那么下一个问题是,对于非散列而言,如何比二次时间做得更好价值观。(并且您也不能假设在这里订购。)将值视图挂起30秒钟,然后返回您直观地想要的答案,而不是在20毫秒内给出错误的答案,这会有所改善吗?(无论哪种方式,您都将学习同一课:不要比较值视图。我宁愿以20毫秒为单位学习。)