This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: dict.__contains__ and dict.keys().__contains__ raises exception instead of returning False
Type: behavior Stage: resolved
Components: Versions: Python 3.4
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: barry, ethan.furman, rhettinger, ronaldoussoren
Priority: normal Keywords:

Created on 2013-07-19 23:43 by ethan.furman, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (5)
msg193384 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2013-07-19 23:43
While working on issue #18508 I stumbled across this:

Traceback (most recent call last):
...
  File "/usr/local/lib/python3.4/enum.py", line 417, in __new__
    if value in cls._value2member_map:
TypeError: unhashable type: 'list'

I'll wrap it in a try-except block, but I must admit I was surprised the answer wasn't False.
msg193391 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2013-07-20 01:27
Commenting further:

    some_key in dict

is conceptually the same as 

    some_key in dict.keys()

which /would/ return False for an unhashable key -- at least it did in 2.x; for 3.x you have to say

    some_key in list(dict.keys())

which seems like a step backwards.

Is it worth changing __contains__ and keys() to be in line with equality?
msg193506 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2013-07-22 06:52
As mentioned on python-dev the current behavior seems sane.

1) Just like __getitem__ and __setitem__, __contains__ raises an 
   exception when the key value cannot be used as a key (which normally
   is a programming error)

2) There are values that compare equal and where one of them is 
   hashable and the other is not, such a set() and frozenset() with
   the same contents. If would be strange if
 
      set([1,2]) in { frozenset([1,2]): 'a' }

   returned False, even though the value is equal to a key in the 
   dictionary.


BTW. I've always interpreted "key in a_dict" as 

       try:
           a_dict[key]
           return True
       except KeyError:
           return False

(and not as equivalent to "key in a_dict.keys()").

(Also, if this behavior were to be changed this would be a new feature and as such could only be added to 3.4 and would IMHO require a PEP)
msg193507 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2013-07-22 07:01
There's no bug here.  It is the way Python has worked for 23 years.
msg193508 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2013-07-22 07:05
I agree, and the thread on python-dev[1] also came to that conclusion, I'm therefore closing this issue.

[1] http://code.activestate.com/lists/python-dev/123385/
History
Date User Action Args
2022-04-11 14:57:48adminsetgithub: 62710
2021-10-25 16:15:27serhiy.storchakalinkissue45605 superseder
2013-07-22 07:05:51ronaldoussorensetstatus: open -> closed
resolution: not a bug
messages: + msg193508

stage: resolved
2013-07-22 07:01:18rhettingersetnosy: + rhettinger

messages: + msg193507
versions: - Python 2.7, Python 3.2, Python 3.3
2013-07-22 06:52:00ronaldoussorensetnosy: + ronaldoussoren
messages: + msg193506
2013-07-20 01:30:09ethan.furmansettitle: dict.__contains__ raises exception instead of returning False -> dict.__contains__ and dict.keys().__contains__ raises exception instead of returning False
2013-07-20 01:29:21ethan.furmansetassignee: ethan.furman ->
versions: + Python 2.7, Python 3.2, Python 3.3, Python 3.4
2013-07-20 01:27:17ethan.furmansetmessages: + msg193391
title: if Enum member value is not hashable an exception is raised -> dict.__contains__ raises exception instead of returning False
2013-07-20 00:02:27barrysetnosy: + barry
2013-07-19 23:43:58ethan.furmancreate