Re: wx.Colour - not hashable in Phoenix/Py3
Robin Dunn <[email protected]>
| Newsgroups | gmane.comp.python.wxpython.devel |
|---|---|
| Message-ID | <[email protected]> |
Werner wrote: > Hi, > > On 11/27/2014 15:26, Amaury Forgeot d'Arc wrote: >> 2014-11-27 14:38 GMT+01:00 Werner <[email protected] >> <mailto:[email protected]>>: >> >> Hi, >> >> On 11/18/2014 15:11, Werner wrote: >> >> I am working on making ObjectListView comptable with Py3 and >> Phoenix and get an error in the tests. >> >> case.py (c:\Python34\Lib\unittest): 57 >> yield >> case.py (c:\Python34\Lib\unittest): 574 >> testMethod() >> test_ObjectListView.py (d:\devTools\ObjectListView\test): 320 >> self.objectListView.oddRowsBackColor in >> set(bkgdColours)) >> testNoAlternateColours >> Exception: TypeError: unhashable type: 'Colour' >> >> >> This test passes with Py2.7 and Phoenix, so it looks like a >> Py3 issue. Anyone has a type on how to fix this? >> >> It looks like the '__hash__' method is not defined in Phoenix >> under Py3.4. >> c = wx.Colour() >> c.__hash__ < returns None >> >> In Py2.7 I get: >> c = wx.Colour() >> c.__hash__ >> <method-wrapper '__hash__' of Colour object at 0x0222AD68> >> >> >> But is it correct? >> For example, can you check whether hash(wx.Colour(1,2,3)) == >> hash(wx.Colour(1,2,3)) ? > In py2.7: > hash(wx.Colour(1,2,3)) == hash(wx.Colour(1,2,3)) > True > > But in py3.4: > c = wx.Colour() > c.__hash__ > hash(wx.Colour(1,2,3)) == hash(wx.Colour(1,2,3)) > Traceback (most recent call last): > File "<string>", line 1, in <fragment> > builtins.TypeError: unhashable type: 'Colour' > > I guess something with the sip magic is not working correctly in Py3.x. > > Hope above will help Robin to pin point it when he gets to this. > From the docs for both Python2 and Python3: """ An object is hashable if it has a hash value which never changes during its lifetime (it needs a __hash__() method), and can be compared to other objects (it needs an __eq__() method). Hashable objects which compare equal must have the same hash value. Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally. All of Python’s immutable built-in objects are hashable, while non mutable containers (such as lists or dictionaries) are not. Objects which are instances of user-defined classes are hashable by default; they all compare unequal (except with themselves), and their hash value is derived from their id(). """ SIP doesn't add a default __hash__ in either build, it just relies on the default Python behavior. In Python2 that seems to be a hash value derived from the object's ID. In other words, you could think of it like this: class HashableColour(wx.Colour): def __hash__(self): return do_something(id(self)) Based on the above text I would have expected the same from Python3, but perhaps the definition of "user-defined classes" was changed to not include extension types. Or maybe that doc needs updating. Either way, I prefer the Python3 way because basing a default hash value on the id() means that you must use the same instance of the key to fetch the value again, you can't simply use a new key with the same value. For example, in Python2: >>> c1 = wx.Colour(1,2,3) >>> c2 = wx.Colour(1,2,3) >>> >>> d = {c1: 'one', c2: 'two'} >>> d[c1] 'one' >>> d[c2] 'two' >>> d[wx.Colour(1,2,3)] Traceback (most recent call last): File "<input>", line 1, in <module> KeyError: wx.Colour(1, 2, 3, 255) >>> In Python3 Python makes you actually think about what makes sense for your class's hash values, it doesn't just give you some mindless substandard thing for free. For wx.Colour I might choose something like: class HashableColour(wx.Colour): def __hash__(self): return self.GetRGBA() or maybe even: return hash(self.Get()) # the hash of the tuple of color components But I suppose the real question is whether we should be adding our own __hash__ methods to at least some of the wrapped wxPython classes. I'll give that some thought. -- Robin Dunn Software Craftsman http://wxPython.org -- You received this message because you are subscribed to the Google Groups "wxPython-dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.