Почему представление ключей OrderedDict не учитывает порядок?

почему OrderedDict keys view сравнить порядок нечувствительным?

>>> from collections import OrderedDict
>>> xy = OrderedDict([('x', None), ('y', None)])
>>> yx = OrderedDict([('y', None), ('x', None)])
>>> xy == yx
False
>>> xy.keys() == yx.keys()
True

представление ключей OrderedDict должно, возможно, вести себя как OrderedSet, но вместо этого оно ведет себя так же, как dict.keys (т. е. как обычный set).

та же" проблема " в python2:

>>> xy.viewkeys() == yx.viewkeys()
True

это разные типы, (odict_keys является наследником dict_keys)

>>> type(xy.keys())
odict_keys
>>> type({}.keys())
dict_keys

и уже сравнение чувствительных к заказу ключей доступно что они мог бы тривиально использоваться, но он, по-видимому, используется только как после проверки для сравнения odict rich.

это дизайнерское решение, или ошибка? Если это проектное решение, где я могу найти обсуждение обоснования?

2 ответов


выглядит так:OrderedDict делегирует реализацию различных объектов представления общему dict реализация; это остается так даже в Python 3.5, где OrderedDict получил ускоренную реализацию C (он делегирует строительство объекта _PyDictView_New и не дает переопределить для общего представления богатая функция сравнения.

по сути, OrderedDict представления повторяются в том же порядке, что и их поддержка OrderedDict будет (потому что это не стоит делать), но для set-подобные операции, они действуют как set, используя равенство контента, проверки подмножества / надмножества и т. д.

это делает выбор игнорировать порядок имеет смысл в некоторой степени; для некоторых set операции (например,&, |, ^), возвращаемое значение set без порядка (потому что нет OrderedSet, и даже если бы они были, какой заказ вы используете для чего-то вроде & где заказ может отличаться в каждый вид?), вы получите непоследовательное поведение, если некоторые из set-подобные операции были чувствительны к порядку, а некоторые-нет. И было бы еще страннее, если бы их было двое!--1--> представления ключей были чувствительны к порядку, но сравнение OrderedDict вид dict представления не было.

как я отметил в комментариях, вы можете получить чувствительный к заказу keys сравнение довольно легко с:

from operator import eq

# Verify that keys are the same length and same set of values first for speed
# The `all` check then verifies that the known identical keys appear in the
# same order.
xy.keys() == yx.keys() and all(map(eq, xy, yx))

# If you expect equality to occur more often than not, you can save a little
# work in the "are equal" case in exchange for costing a little time in the
# "not even equal ignoring order case" by only checking length, not keys equality:
len(xy) == len(yz) and all(map(eq, xy, yx))

Я не могу найти ничего опубликованного, но я думаю, что эта логика может оправдать поведение:

если у вас есть два словаря, d1 и d2, вы ожидаете, что сравнение ключей проверяет, имеют ли они одинаковые ключи, верно?

def compare_dict_keys(d1, d2):
    d1.keys() == d2.keys()

эта функция должна вести себя одинаково для любых типов словарей (и OrderedDict тип dict). Казалось бы, неправильно, если такая функция начала возвращать False только потому, что D1 и d2 отсортированы.

In другими словами, все они должны оценивать одно и то же (и они это делают):

>>> {1:2, 3:4}.keys() == {3:4, 1:2}.keys()
True
>>> {1:2, 3:4}.keys() == OrderedDict([(3,4),(1,2)]).keys()
True
>>> OrderedDict([(1,2),(3,4)]).keys() == OrderedDict([(3,4),(1,2)]).keys()
True

но OrderedDict это specal, не так ли?

что OrderedDict предлагает вам гарантию заказа, когда вы повторяете его. Такая же гарантия существует для OrderedDict.keys(), но без нарушения совместимости с dict.