FancyHashMixin: like FancyEqMixin but for __hash__
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 6k
- Forks
- 1.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 10
Description
| @lvh reported | |
|---|---|
| Trac ID | trac#4613 |
| Type | enhancement |
| Created | 2010-07-24 13:37:52Z |
Right now FancyEqMixin has a somewhat strange (and I would argue broken) behavior:
>>> from twisted.python.util import FancyEqMixin
>>> class C(object, FancyEqMixin):
... compareAttributes = "a",
...
... def __init__(self, a):
... self.a = a
...
>>> c1, c2 = C(1), C(1)
>>> c1 is not c2 and c1 == c2 and hash(c1) != hash(c2)
True
(The problem being that C.__hash__ == object.__hash__; which hashes on id.)
I'm fairly certain that c1 == c2 ==> hash(c1) == hash(c2). I propose that FancyEqMixin grows a __hash__ method that raises NotImplementedError. This will not break backwards compatibility; when it does break existing code that code was wrong anyway. The problem with that is that if something else does implement a working __hash__ it's hard to guarantee that the good __hash__ is lower in the MRO (eg gets used), plus it breaks cooperative MI if the good __hash__ uses __hash__es from further up in the MRO. Not sure what the right way to fix that is. I think you should implement __hash__ on the level you introduce the mixin anyway?
thrashold has suggested __hash__ = None on IRC, that would raise TypeError; not really the TypeError I would want (I would expect to see "type x is not hashable" rather than something about None not being callable, but apparently this is how you disable hash?
This is new in 2.6:
Changed in version 2.6: __hash__ may now be set to None to explicitly flag instances of a class as unhashable.
[http://docs.python.org/reference/datamodel.html#object.hash]
2.6 actually does the right thing automagically (which is this), but only on new-style classes, it appears.
Anyway, I propose a FancyHashMixin that has a hashAttributes classattr like FEM has a compareAttributes classattr and then hashes on the value of [getattr(self, v) for v in self.hashAttributes]. I think it should also subclass FEM; if we can count on cooperative MI (which we can't due to old-style classes) the default value for hashAttributes could be compareAttributes, since in 90% of cases they will be the same (as long as hashAttributes is a subset of compareAttributes it will still behave correctly).
Ceterum censeo geventem et medusam esse delendam.
Attachments:
- fancyhashmixin-4613.diff (4727 bytes) - added by lvh on 2010-09-17 21:32:42Z -
- fancyhashmixin-4613.2.diff (11113 bytes) - added by lvh on 2010-10-07 17:14:29Z -
Searchable metadata
trac-id__4613 4613
type__enhancement enhancement
reporter__lvh lvh
priority__lowest lowest
milestone__
branch__
branch_author__
status__new new
resolution__None None
component__core core
keywords__
time__1279978672000000 1279978672000000
changetime__1295883905000000 1295883905000000
version__None None
owner__
cc__awclin
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with FancyEqMixin in twisted.python.util and read the issue's discussion of hash, hash = None, cooperative multiple inheritance, and old-style classes. Compare the two attached diffs to understand the proposed directions. Done means reaching a decided design for FancyHashMixin and confirming that equality and hashing remain consistent under the documented Python behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100