Niestety, obie aktualne odpowiedzi nie wyjaśniają, dlaczego tak jest, ale koncentrują się na tym, jak to się robi.Że lista dyskusyjna dyskusja była niesamowita, więc będę Podsumowując rzeczy:
Dla odict.keys
/dict.keys
i odict.items
/dict.items
:
odict.keys
(subclass of dict.keys
) obsługuje porównania ze względu na jego zgodność z collections.abc.Set
(jest to zestaw podobny obiekt). Jest to możliwe dzięki temu, że keys
w słowniku (uporządkowanym lub nie) jest gwarantowane, że jest unikalne i niehieralne.
odict.items
(subclass of dict.items
) obsługuje również porównanie z tego samego powodu co .keys
. itemsview
może to zrobić, ponieważ podnosi odpowiedni błąd, jeśli jeden z item
s (konkretnie, drugi element reprezentujący wartość) nie jest hashable, wyjątkowość jest gwarantowany, choć (ze względu na keys
jest unikatowy):
>>> 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'
Dla obu tych widoków keys
, items
, porównanie wykorzystuje prostą funkcję o nazwie all_contained_in
(całkiem czytelna), która wykorzystuje metodę obiektów __contain__
do sprawdzania członkostwa elementów w widokach.
Teraz o odict.values
/dict.values
:
Jak zauważył, odict.values
(subclass of dict.values
[szok]) nie porównać jak przedmiot podobny do zadanej. To dlatego, że values
z valuesview
nie może być przedstawiony jako zbiór, powody są dwojakie:
- Co najważniejsze, widok może zawierać duplikatów, które nie mogą być pominięte.
- Widok może zawierać nieściągalne obiekty (które same w sobie nie wystarczą do tego, aby widok nie był traktowany jako podobny).
Jak podano w komentarzu przez @user2357112 i @abarnett na liście mailingowej, odict.values
/dict.values
jest multiset, uogólnienie zbiorów, która pozwala wiele wystąpień na jego elementy. Próba porównania nie jest tak banalna jak porównanie keys
lub items
z powodu nieodłącznego powielania, porządku i faktu, że prawdopodobnie trzeba wziąć pod uwagę klucze, które odpowiadają tym wartościom. Powinien dict_values
że wyglądać tak:
>>> {1:1, 2:1, 3:2}.values()
dict_values([1, 1, 2])
>>> {1:1, 2:1, 10:2}.values()
dict_values([1, 1, 2])
faktycznie równe, chociaż wartości, które odpowiadają kluczy nie jest taki sam? Może? Może nie? Nie jest to ani jednoznaczne i doprowadzi do nieuchronnego zamieszania.
Punktem być wykonane jest jednak, że to nie jest trywialne, aby porównać je z keys
jak i items
, podsumowując, z innym komentarzem @abarnett na the mailing list:
Jeśli jesteś myśląc, że możemy zdefiniować to, co multisetyki powinny robić, pomimo braku standardowego typu multiset lub ABC dla nich, i zastosować to do wartości poglądów, następne pytanie brzmi: jak to zrobić w czasie lepszym niż czasy kwadratowe dla nie-stabilnych wartości. (I nie można również zakładać zamawiania tutaj.) Czy posiadanie widoku wartości zawiesiłoby się na 30 sekund, a następnie wróciłoby z odpowiedzią, której intuicyjnie potrzebowałeś, zamiast dać błędną odpowiedź w 20 milimitach, aby poprawić? (Tak czy inaczej, nauczymy się tej samej lekcji: nie porównuj wartości poglądów. Wolałbym nauczyć się tego w 20 milach.)
Działa dobrze na Pythonie 2.7.6 –
** 'dykt. values' ** zwraca wartość [** 'ValuesView' **] (https://docs.python.org/3/glossary.html#term-dictionary-view) –