Issue 26614: False/0 and True/1 collision when used as dict keys? (original) (raw)

Issue26614

Created on 2016-03-23 03:04 by nickeubank, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (4)
msg262232 - (view) Author: nickeubank (nickeubank) Date: 2016-03-23 03:03
Found an odd behavior I'd never known about today, not sure if it's a bug or known. Python 3.4.4 (anaconda) True, False, 0, 1 can all be used as dictionary keys. But Apparently True and 1 hash to the same item and False and 0 hash to the same item, so they can easily overwrite (which I spent a while banging my head over today). In other words: In[1]: d = {True: 'a', False: 'b'} d[0] = 'z' d[False] Out[1]: 'z'
msg262234 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2016-03-23 03:11
False and True are subtypes of int, so the behaviour you are seeing is known and expected. https://docs.python.org/2/reference/datamodel.html?highlight=bool In the future feel free to ask on Python-List about behaviour -- you'll be sure to get a plethora of answers.
msg262336 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2016-03-24 12:34
"Apparently True and 1 hash to the same item and False and 0 hash to the same item" Just to clear up a possible misconception here, the key point here is not that they hash to the same integer, but that they're *equal*: >>> True == 1 True >>> False == 0 True In contrast, here are two elements whose hash is equal but which serve as distinct keys: >>> hash(-1) == hash(-2) True >>> len({-1: -1, -2: -2}) 2 IOW, dictionary semantics are defined in terms of equality, not hashing. The hashing part should really be thought of as just a (somewhat exposed) implementation detail.
msg262338 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2016-03-24 12:47
Many values have the same hash value, it's not an issue. The hash is only a best effort function to reduce hash collision, but hash collision is well handled in the dict type (as explained in other messages). >>> hash(1) == hash(1.0) == hash(1.0+0j) == 1 True >>> hash('') == hash(b'') == hash(0) == hash(0.0) == hash(0.0j) == 0 True
History
Date User Action Args
2022-04-11 14:58:28 admin set github: 70801
2016-03-24 12:47:51 vstinner set nosy: + vstinnermessages: +
2016-03-24 12:34:38 mark.dickinson set nosy: + mark.dickinsonmessages: +
2016-03-23 03:11:09 ethan.furman set status: open -> closednosy: + ethan.furmanmessages: + resolution: not a bugstage: resolved
2016-03-23 03:04:00 nickeubank create