On Oct 1, 2019, at 15:59, Chris Angelico <rosuav@gmail.com> wrote:
On Wed, Oct 2, 2019 at 8:51 AM Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
Chris Angelico wrote:
The question then would be: why is object() not hashable?
It's not hashable because it's supposed to be the ultimate base type for all other objects, and not every object is hashable.
It only seems odd if you're used to the idea that you get a bunch of default behaviours from object, including hashability. But if you want strict subtyping and also an ultimate base type, the base type has to include very little behaviour.
Should the default object be comparable? Or would there be a "Comparable" subtype? If object() can be compared for equality with another object(), then it'd be illogical to make it unhashable - there's no reason to deny hashing. If it can't be compared, why not? Why should the base type include THAT little behaviour?
This really is a practicality-vs.-purity question. Theoretically, it is wrong to include any behavior in your top type that is not supported by every other type in the system. Practically, it is useful to include behavior in your top type that is used by _most_ types in the system and would be a pain to reimplement over and over again, even if it isn’t supported by all types. Different languages solve part of that balance by having a lot of decorators, or mixin classes, or macros, or magic flags to the implementation. (Or you even could go Smalltalk style, and different environments will add different methods to Object.) Python does some of that too—functools.total_order, and some of the collections.abc types being their own mixins, etc. But it still gets tedious to include six mixins and four decorators on 90% of your types, so Python compromises purity and moves some of that stuff into object. So, object is hashable, and that means some types that are going to pass an is-a test for object are going to violate LSP. (Obviously that’s not the actual design history of Python—Guido didn’t decide to add object.__hash__ only after imagining the future of multiple inheritance and decorators, and comparing how the three different design choices would impact all the dict code people we’re going to write in future decades. But you get the idea.)