python / cpython

The Python programming language
https://www.python.org
Other
63.18k stars 30.25k forks source link

Docs: Clarification needed on dictionary key requirements, Hashable vs. Immutable #110270

Open mousehead opened 1 year ago

mousehead commented 1 year ago

Documentation

5.5. Dictionaries

Unlike sequences, which are indexed by a range of numbers, dictionaries are indexed by keys, which can be any immutable type; strings and numbers can always be keys. Tuples can be used as keys if they contain only strings, numbers, or tuples; if a tuple contains any mutable object either directly or indirectly, it cannot be used as a key. You can’t use lists as keys, since lists can be modified in place using index assignments, slice assignments, or methods like append() and extend().

Formally, mutability is not the reason why you can't use lists as keys, the only factor that matters is hashability, and it was decided to make list unhashable to avoid "undesirable side effects". This is articulated in the DictionaryKeys section of the Python Wiki.

Consider this:

class HashableList(list):
    def __hash__(self):
        return id(self)

key = HashableList([1, 2])
d = {key: True}
key.append(3)
print(d)  # prints {[1, 2, 3]: True}

This code, albeit weird, is perfectly valid. Clearly, .append() is not what prevents lists from being used as keys.

While mutability might be a reason why you shouldn't use something as a key, it's never the reason why you can't. This section in the tutorial doesn't make it clear and could bring more confusion about the inner workings, and the part of the documentation emphasised in italic is factually false.

I suggest rephrasing the section to clarify that the primary requirement for dictionary keys is hashability, not immutability. While many immutable types are hashable by default in Python, the two concepts are distinct.

AA-Turner commented 1 year ago

The content you referenced is in the tutorial, where we can be a little more fuzzy with concepts. Note currently 'hash' doesn't appear on the page at all.

A