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 -- https://mail.python.org/mailman/listinfo/python-list