Are instances of user-defined classes mutable?

Richard Damon Richard at Damon-Family.org
Fri Aug 7 11:00:55 EDT 2020


On 8/6/20 10:53 PM, ZHAOWANCHENG wrote:
> So instances of user-defined classes are immutable by default?
> Or the description of "if a tuple contains any mutable object either
> directly or indirectly, it cannot be used as a key." in the document
> is not completely correct?
> The description mentioned above comes from here:
> https://docs.python.org/3/tutorial/datastructures.html#dictionaries

My answer was pointing out in a very abstract sense, it is perhaps
tricky to define what is 'mutability' for a class as it affects its use
in a dictionary.

The key here is to ask what does using a class as a key (or part of a
key with a tuple) means.

You build the dictionary, use a key value, and then you can look up that
entry by passing an equal value key, and it will find the term.

So we need to look at what it means for class objects to be equal, and
the default for that checks for equality of the id(), not any of the
members.

This means that doing something like:

a = myclass(10)

b = myclass(10)

d = { a: 1}

trying to do a

d[b] will throw a KeyError exception, as there is no item in the dict
with that key.

and if we ask a == b we get false (even though all their values match)

This comes to the point that, for a class with the default equality
operator, so equality is identity, do changing a member of a class
object REALLY mutate the object as far as the dictionary is concerned?
Changing the member value does NOT change what the key represents.

Note also, once you define the equality testing function __eq__, then
python makes the class non-hashable (unless you also define a __hash__
function) so a class like that can't be used as a part of a key in a
dictionary, because it now has the ability to 'change' the value it
represents.

Going back to the original issue. A tuple can normally be used as a
dictionary key (but a list can not) because it can build its hash as a
combination of the hash for all its elements (as long as they are
hashable, and the 'immutable' objects are) and thus be usable as a key.
Since a list, unlike a tuple, allows you to mutate  the sequence by
modifying the list, it can't provide the unchangable hash by the same
method.

When you put a class object into the tuple, as long as it still has it
__hash__ member, because you haven't defined a __eq__ member, is at
least to the tuple, immutable, as the only part of it that matters is
the value of id() which WILL be unchanging.

-- 
Richard Damon



More information about the Python-list mailing list