The concept of "hashable" and "unhashable" classes has been a bit of the sore point in the past. typeshed uses __hash__: ClassVar[None] to mark classes as non-hashable, although that requires a # type: ignore[assignment] annotation. I think this is special-cased by at least some type checkers for marking classes as unhashable.
Except for some wordage in the dataclasses section, the typing spec is silent about hashability. Since I believe that this needs special-casing by type checkers, it should be added to the typing spec. A raw idea:
- Classes are hashable by default (due to
object.__hash__() being implemented and typeshed having a type corresponding type annotation.)
- To mark a class as non-hashable, use
__hash__: ClassVar[None]. We could alternatively use something simpler such as __hash__ = None. I believe we used to use that, but I don't know why it's changed.
- To mark a class as hashable, use
def __hash__(self, ...) -> ..., usually def __hash__(self) -> int: ....
- Sub-classes inherit their parent's hashability, unless overridden.
The concept of "hashable" and "unhashable" classes has been a bit of the sore point in the past. typeshed uses
__hash__: ClassVar[None]to mark classes as non-hashable, although that requires a# type: ignore[assignment]annotation. I think this is special-cased by at least some type checkers for marking classes as unhashable.Except for some wordage in the dataclasses section, the typing spec is silent about hashability. Since I believe that this needs special-casing by type checkers, it should be added to the typing spec. A raw idea:
object.__hash__()being implemented and typeshed having a type corresponding type annotation.)__hash__: ClassVar[None]. We could alternatively use something simpler such as__hash__ = None. I believe we used to use that, but I don't know why it's changed.def __hash__(self, ...) -> ..., usuallydef __hash__(self) -> int: ....