Ответ 1
Краткий ответ: class dict_values
не имеет __eq__
метода __eq__
, но class dict_keys
делает:
>>> d.values().__eq__(d.values())
NotImplemented
>>> d.keys().__eq__(d.keys())
True
Поэтому сравнение d.values()
==
оценивается как False
.
Более длинный ответ о том, почему он не был реализован, - другой, и его можно увидеть, немного покопавшись в документации объектов dict-view. Эта часть кажется особенно актуальной (выделено мной):
Представления ключей похожи на наборы, поскольку их записи уникальны и доступны для хэширования. Если все значения могут быть хэшируемыми, поэтому пары (ключ, значение) уникальны и хэшируемы, то представление элементов также задается как набор. (Представления значений не обрабатываются как подобные множеству, так как записи, как правило, не являются уникальными.) Для представлений, подобных множеству, доступны все операции, определенные для
collections.abc.Set
абстрактного базового класса .abc.Set (например,==
,<
или^
).
Поскольку ключи должны быть уникальными, имеет смысл, что они подобны множеству и поддерживаются операциями с классами collections.Set
. Значения не установлены как из-за неединственности.
Однако в Python 2.7 и d.keys()
и d.values()
возвращают list
соответствии с документацией, поэтому это ограничение не применяется. Поскольку оба объекта относятся к одному и тому же типу, имеет смысл использовать одну и ту же операцию для обоих. Если вы использовали viewkeys
и viewvalues
как упомянуто в документации объектов dict-view в Python2.7, то вы можете ожидать аналогичного поведения:
# Python 2.7
from collections import Set
# in Python 3.x this would be from collections.abc import Set
d = {"one": 1}
print isinstance(d.viewkeys(), Set)
# True
print isinstance(d.viewvalues(), Set)
# False
print d.viewkeys() == d.viewkeys()
# True
print d.viewvalues() == d.viewvalues()
# False