Почему клавиши "OrderedDict" сравнивают нечувствительность к порядку? - программирование
Подтвердить что ты не робот

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

Почему вид клавиш OrderedDict сравнивается с нечувствительным к регистру?

>>> 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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

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

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

>>> {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.