Veek M wrote: > Jussi Piitulainen wrote: > >> Veek M writes: >> >> [snip] >> >>> Also if one can do x.a = 10 or 20 or whatever, and the class >>> instance is mutable, then why do books keep stating that keys need >>> to be >>> immutable? After all, __hash__ is the guy doing all the work and >>> maintaining consistency for us. One could do: >>> >>> class Fruit: >>> editable_value = '' >>> def __hash__(self): >>> if 'apple' in self.value: >>> return 10 >>> elif 'banana' in self.value: >>> return 20 >>> >>> >>> and use 'apple' 'bannana' as keys for whatever mutable data.. >>> Are the books wrong? >> >> The hash does not do all the work, and the underlying implementation >> of a dictionary does not react appropriately to a key changing its >> hash value. You could experiment further to see for yourself. >> >> Here's a demonstration that Python's dictionary retains both keys >> after they are mutated so that they become equal, yet finds neither >> key (because they are not physically where their new hash value >> indicates). >> >> I edited your class so that its methods manipulate an attribute that >> it actually has, all hash values are integers, constructor takes an >> initial value, objects are equal if their values are equal, and the >> written representation of an object shows the value (I forgot >> quotes). >> >> test = { Fruit('apple') : 'one', Fruit('orange') : 'two' } >> >> print(test) >> print(test[Fruit('orange')]) >> # prints: >> # {Fruit(apple): 'one', Fruit(orange): 'two'} >> # two >> >> for key in test: key.value = 'banana' >> >> print(test) >> print(test[Fruit('banana')]) >> >> # prints: >> # {Fruit(banana): 'one', Fruit(banana): 'two'} >> # Traceback (most recent call last): >> # File "hash.py", line 25, in <module> >> # print(test[Fruit('banana')]) >> # KeyError: Fruit(banana) > > ah! not so: that's because you are messing/changing the integer value > for the key. If apple-object was returning 10, you can't then return > 20 (the text mangling seems to be completely irrelevant except you > need it to figure out which integer to return but barring that..). > > Here's an example of what you're doing (note 'fly' is returning 20 BUT > the object-instance is 'apple' - that obviously won't work and has > nothing to do with my Q, err.. (don't mean to be rude): > class Fruit(object): > def __init__(self, text): > self.text = text > > def mangle(self,text): > self.text = text > > def __hash__(self): > if 'apple' in self.text: > return 10 > elif 'orange' in self.text: > return 20 > elif 'fly' in self.text: > return 20 > else: > pass > > apple = Fruit('apple') > orange = Fruit('orange') > > d = { apple : 'APPLE_VALUE', orange : 'ORANGE_VALUE' } > print d > > apple.mangle('fly') > print d[apple] > > The Question is specific.. what I'm saying is that you can change > attributes and the contents and totally mash the object up, so long as > __hash__ returns the same integer for the same object. Correct? > > Where does __eq__ fit in all this?
How does MUTABILITY play a role in this?? __hash__ *HAS* to return an integer which is immutable anyhow.. And as far as UDT's are concerned they don't need to be immutable, they just need to return their integer- key correctly.. -- https://mail.python.org/mailman/listinfo/python-list