Why KeyError instead of ValueError in the case of sets?

I have the following code :

set_a={1,2,3}
set_a.remove(4) # error here

It produces the following error message :

KeyError : 4

If I modify the code as :

list_a=[1,2,3]
list_a.remove(4)

The output is

ValueError : list.remove(x) : x not in list

Why does the Python interpreter provides KeyError in the case of sets instead of ValueError as in the case of lists?

Keys are associated with dicts therefore are sets linked with dicts?

Or are set members called as keys? If so the reason for that please.

Yes, sets and dicts are very similar. Dicts were the original data structure in python2. You could implement a set as just the keys of a dict (no values). So the current set implementation exposes some of the underlying dict machinery with KeyError.

List data isn’t stored by key/hash. Removing an element by value requires searching the list and matching a particular value.

Even if it gives ValueError, will it affect anything. Could you please answer this?

Even if what gives ValueError?

The documentation on the methods describe the errors might arise. For sets, remove() and pop() may throw a KeyError. ValueError should not be possible.

Set Types 
...
remove(elem)
Remove element elem from the set. Raises KeyError if elem is not contained in the set.
...
pop()
Remove and return an arbitrary element from the set. Raises KeyError if the set is empty.

Whereas for lists, ValueError can be generated.

Lists
...
3. remove() raises ValueError when x is not found in s.

Hence the reason for KeyError is that the set elements are hashable and resemble dict keys. Am I right? Is it the actual reason?

Essentially. They’re very much like dicts whose values are also the
keys. SO it has the same behaviours.

Changing to ValueError now (versus in the distant past at the design
phase) would break any code using KeyError to detect an attempt to
remove an element which was not present.

And because sets are a lot like dicts, people (waves ahnds vaguely)
would probably rather get a KeyError anyway.

A ValueError tends to mean an unsuitable value. A KeyError or IndexError
means a value which was not present. And IndexError is for indices -
generally a sequence such as the int index on a list - and KeyError is
for other things.

Cheers,
Cameron Simpson cs@cskk.id.au

I can understand your explanation. But I just had a lay man’s doubt. What if set also returns a ValueError as list like this :

ValueError : set.remove(x) : x not in set

This may seem silly. But please spare your valuable time yo answer this please

It will break the code which expects a KeyError. Are you ready to take responsibility for this?

Hi Sanmitha,

We’re not going to change the exception raised by sets. As Serhiy says,
changing the exception would break thousands of programs that expect
set.remove to raise KeyError.

If you want to remove an item from a list or a set, and you’re not sure
which, you can write this:

# collection might be a list, or a set
try:
    collection.remove(item)
except (KeyError, ValueError):
    # item not found
    ...

No need to change set.