Home > Software design >  Use lists to get objects in dictionary but not as keys
Use lists to get objects in dictionary but not as keys

Time:03-18

I was a bit surprised when I tried to do

if list in dict:

and got

TypeError: unhashable type: 'list'

I know it does not make sense to use lists as keys as they are mutable and their hash could change when you do operations on them. However, why is it not possible to use them to simply look up objects in a dictionary? I know it is not much work doing

if tuple(list) in dict:

rather than just

if list in dict:

But still, I feel like it would work as default behavior as the hash of its current elements should be the exact same thing as the hash of the corresponding tuple that may be in the dictionary? Or am I missing something in what makes lists unusable in dictionaries?

CodePudding user response:

While I don't think "why does Python work like that" questions are on-topic for this site, I'm gonna say this seems like a terrible idea. You are not supposed to (cannot) use lists as keys in a dictionary, so why would you expect them to be among the keys? If you are looking for a tuple, why would you want to pass a list instead?

CodePudding user response:

Actually, you can calculate hash of a list (as any other sequence of bits) and implement desired behavior.

Hovewer,

  • tuples are immutable objects, hash of a tuple may be calculated once, at initialization
  • lists are mutable. They may change its state and hashing based on elements of a list will produce different hashes, if state was changed. So, using this hashing method, hash of list can't be precalculated

Now consider in operation.

When you check a_tuple in a_dict, hash of a_tuple is known, and in operation takes linear time O(len(a_dict)).

Suppose, that someone implemented a_list in a_dict operation. This would take O(len(a_list)) O(len(a_dict)) time, because you have to calculate hash of a_list. Therefore, unintended behavior happens.

On other hand, if we consider another hashing method that takes O(1), e.g. just by link to an object. You will get another behavior of a_list in a_dict. Because if a_list == b_list and not a_list is b_list, then (a_list in a_dict) != (b_list in a_dict).

Also, notice that

Tuples can be used as keys if they contain only strings, numbers, or tuples

  • Related