[Python-Dev] dict __contains__ raises TypeError on unhashable input

Guido van Rossum guido at python.org
Sun Jul 21 04:37:02 CEST 2013


On Sat, Jul 20, 2013 at 6:37 PM, Ethan Furman <ethan at stoneleaf.us> wrote:
> On 07/20/2013 03:21 AM, Ronald Oussoren wrote:
>>
>>
>> On 20 Jul, 2013, at 1:47, Ethan Furman <ethan at stoneleaf.us> wrote:
>>
>>> 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.  After all, if the input is unhashable then obviously
>>> it's not in the dict; furthermore, if I were to compare the number 5 with a
>>> set() I would get False, not a TypeMismatch error, and dict keys are
>>> basically done by equality, the hash is just (?) a speed-up.
>>
>>
>> Not quite, there are some objects that compare equal without both of them
>> being hashable:
>>
>>>>> frozenset([1,2]) == set([1,2])
>>
>> True
>>>>>
>>>>> dct = { frozenset([1,2]): 1 }
>>>>> frozenset([1,2]) in dct
>>
>> True
>>>>>
>>>>> set([1,2]) in dct
>>
>> Traceback (most recent call last):
>>    File "<stdin>", line 1, in <module>
>> TypeError: unhashable type: 'set'
>>
>> It would be strange if the last test would return False instead of raising
>> an error.
>
>
> Yeah, that would be unfortunate.
>
> Okay, I can see dict.__contains__ and friends raising a TypeError, but what
> about dict.keys() ?  In 2.x it returned a list, in 3.x it returns a
> dict_keys, and dict_keys also raises an error instead of returning False.

The same reasoning applies. And the Python 2 and 3 keys() methods are
so different that the backwards compatibility argument doesn't really
have any weight.

-- 
--Guido van Rossum (python.org/~guido)


More information about the Python-Dev mailing list