On 30.06.20 05:08, Steven D'Aprano wrote:
On Tue, Jun 30, 2020 at 11:10:20AM +0900, Inada Naoki wrote:On Mon, Jun 29, 2020 at 9:12 PM Hans Ginzel <hans@matfyz.cz> wrote:What are the reasons, why object dict.items() is not subscriptable – dict.items()[0]?Because dict is optimized for random access by key and iteration, but not for random access by index.But we're not talking about *dict*, we're talking about dict.items which returns a set-like object: py> from collections.abc import Set py> isinstance({}.items(), Set) True So dict.items isn't subscriptable because it's an unordered set, not a sequence.
What is the reason for `dict.items` to return a set-like object? The values can be non-hashable an in this case the behavior can be surprising:
>>> {'a': []}.items() & {'b'}
TypeError: unhashable type: 'list'
Furthermore [the documentation](https://docs.python.org/3/library/stdtypes.html#dict-views) states the following:
> If all
values are hashable, so that (key, value)
pairs are unique and hashable,
then the items view is also set-like.
This sounds like the return type of `dict.items` depended on the actual values contained (which again would be surprising) but actually it doesn't seem to be the case:
>>> from collections.abc import Set
>>> isinstance({'a': []}.items(), Set)
True
`dict.items` could provide all of its "standard" behavior (like membership testing, reversing, etc) without being set-like.
The fact that `==` with `dict.items` raises TypeError for non-hashable values is also a little surprising since it supports membership testing and hence could check `len(self) == len(other) and all(x in self for x in other)` (though that drops the type comparison, but if you cannot have a set, why would you compare them anyway):
>>> self = {'a': []}.items()
>>> other = {('a', 1)}
>>> self == other
TypeError: unhashable type: 'list'
>>> len(self) == len(other) and all(x in self for x
in other)
False
>>> other = [('a', [])]
>>> len(self) == len(other) and all(x in self for x
in other)
True