Skip to content

Confusion with "immutable" and "hashable" in Design and History FAQ #134114

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
plusquant opened this issue May 16, 2025 · 5 comments
Closed

Confusion with "immutable" and "hashable" in Design and History FAQ #134114

plusquant opened this issue May 16, 2025 · 5 comments
Labels
docs Documentation in the Doc dir

Comments

@plusquant
Copy link

plusquant commented May 16, 2025

The page https://docs.python.org/3/faq/design.html#why-are-there-separate-tuple-and-list-data-types says at the end of its last paragraph:

Only immutable elements can be used as dictionary keys...

Which is not quite correct, since dictionaries only require its keys to be hashable (see https://docs.python.org/3/library/stdtypes.html#mapping-types-dict). Immutability doesn't necessarily imply hashability.

Thanks.

Linked PRs

@skirpichev
Copy link
Contributor

Immutability doesn't necessarily imply hashability.

Immutability is more strong requirement, it does.

@ryan-duve
Copy link
Contributor

Is there an immutable element that can not be used as a dictionary key? Or a mutable element that can be used as a dictionary key?

@plusquant
Copy link
Author

plusquant commented May 17, 2025

According to https://docs.python.org/3/glossary.html#term-hashable

Most of Python’s immutable built-in objects are hashable...

It means that there are some kind of immutable built-in objects that aren't hashable.

Additionally, you can make a class that doesn't implement __eq__ and/or __hash__ (by definition, it must have both in order to make the objects hashable) that does produce objects with immutable values. As a result, the objects will be immutable but still unusable as dict keys.

@skirpichev
Copy link
Contributor

It means that there are some kind of immutable built-in objects that aren't hashable.
[...] Additionally, you can make a class that doesn't define __eq__ and/or __hash__

I would say, it's just an implementation detail. I.e. yes, you could break default hashability (per default, derived from the object class types are hashable) - by setting __hash__ = None. But there is no good reasons to do this for immutable objects.

Is there an immutable element that can not be used as a dictionary key?

Sure, you can create an artificial type:

class BadObj:
    __hash__ = None

@Locked-chess-official
Copy link

Is there an immutable element that can not be used as a dictionary key? Or a mutable element that can be used as a dictionary key?是否存在不可用作字典键的不可变元素?或者存在可用作字典键的可变元素?

Yes.

class CannotBeChangedClass:
    slots = ('value',)
    def __new__(cls, value):
        a=super().__new__(cls)
        object.__setattr__(a,'value',value)
        return a

    def __setattr__(self, item, value):
        raise AttributeError

    def __delattr__(self, item):
        raise AttributeError

    def __eq__(self, other):
        return self.value == other.value

This class is unhashable (have no hash) so it cannot be the key of dict.

class CanBeChangedClass:
    def __init__(self, value):
        self.value = value

This class is changedable, but if a class has no "eq", the hash is default to use the hash of id, so it is hashable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Documentation in the Doc dir
Projects
Status: Todo
Development

No branches or pull requests

5 participants