Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set your subtitle preferences in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please refer to our video player troubleshooting guide for assistance.

Restrictions on Dictionary Keys and Values

Almost any type of value can be used as a dictionary key in Python. You can even use built-in objects like types and functions. However, there are a couple restrictions that dictionary keys must abide by.

First, a given key can appear in a dictionary only once. Duplicate keys are not allowed. A dictionary maps each key to a corresponding value, so it doesn’t make sense to map a particular key more than once. If you specify a key a second time during the initial creation of a dictionary, then the second occurrence will override the first.

Second, a dictionary key must be of a type that is immutable. For example, you can use an integer, float, string, or Boolean as a dictionary key. However, neither a list nor another dictionary can serve as a dictionary key, because lists and dictionaries are mutable. Values, on the other hand, can be any type and can be used more than once.

00:00 You’ve seen so far that dictionaries are very flexible, kind of an awesome data type to work with. But there are a few restrictions I want to briefly talk about. Keys in a dictionary can only be used once. If it is used more than once, as you saw earlier, it’ll simply replace the value.

00:19 A key must be immutable—that is, unable to be changed. These are things like integers, floats, strings, Booleans, functions. Even tuples can be a key. A dictionary or a list cannot be a key. Values, on the other hand, can literally be anything and they can be used more than once.

00:41 Let’s hop into the console for a couple of examples. You’ve seen so far that you can use values of all sorts in a dictionary. The same goes for keys. You don’t have to simply use strings or integers—you can use floats, Booleans, even tuples as keys.

01:00 If we open up an example dictionary here and let’s give it a couple of keys of those types.

01:13 There’s a Boolean. And let’s try with a tuple here.

01:25 Go ahead and close this dictionary off. And you can see it took those without exception. And even call one of those—no problem! So, remember the restrictions we talked about.

01:41 They can only be used once in a dictionary and keys must also be immutable. So, what happens if we use one of those mutable data types? Like a list as a key?

02:02 And try to assign it? Oops, I have plural examples. So you can look here, and our second exception that we got—unhashable type: 'list'.

Joshua Dougas on Sept. 23, 2021

I was suprised that the error message for list keys does not mention mutability at all!

I played around and found that mutable objects actually do work as keys, as long as the object is hashable. We can make a descendant list that is hashable by implementing the hash() method using some arbitrary scheme.

I did this below and found that mutable objects do in fact work as dictionary keys, it is just that using mutable keys may lead to unexpected results.

For example if you add a item using a mutable key and then irreversibly change the key, then you risk ‘loosing’ the associated value. I’m sure there are a bunch of other caveats, such as with collisions, as well.

>>> class HashableList(list):
    def __hash__(self):
        custom_hash = hash(bool(self) and self[0])
        print(f'Custom hash for {self}: {custom_hash}.')
        return custom_hash

>>> mutable_key = HashableList([1,2,3])
>>> immutable_key = 'Strings are immutable'
>>> d = {mutable_key:'Mutable',
     immutable_key:'Immutable'}
Custom hash for [1, 2, 3]: 1.
>>> print(d[mutable_key])
Custom hash for [1, 2, 3]: 1.
Mutable
>>> print(d[immutable_key])
Immutable
>>> mutable_key[1] = -1
>>> print(d[mutable_key])
Custom hash for [1, -1, 3]: 1.
Mutable
>>> print(d)
{[1, -1, 3]: 'Mutable', 'Strings are immutable': 'Immutable'}
>>> mutable_key[0] = 99
>>> try:
  print(d[mutable_key])
  print('Mutated key worked!')
except:
  print(f'{mutable_key} is not a valid key')


Custom hash for [99, -1, 3]: 99.
[99, -1, 3] is not a valid key
>>> mutable_key[0] = 1
>>> print(d[mutable_key])
Custom hash for [1, -1, 3]: 1.
Mutable

Become a Member to join the conversation.