On Thu, Aug 06, 2020 at 12:17:17PM +0800, ZHAOWANCHENG wrote:
> the doc of dictionary said "if a tuple contains any mutable object either 
> directly or indirectly, it cannot be used as a key."
> i think a instance of user-defined class is mutable, but i found it can be 
> placed into a tuple that as a key of a dict:
>     >>> class mycls(object):
>     ...     a = 1
>     ...
>     >>> me = mycls()
>     >>> me.a = 2  # mutable?
>     >>> {(1, me): 'mycls'}
>     {(1, <__main__.mycls object at 0x0000022824DAD668>): 'mycls'}
>     >>>
> 
> 
> So are instances of user-defined classes mutable or immutable?

A more specific description of objects that can be keys in a dictionary 
can be found on the documentation:

https://docs.python.org/3/library/stdtypes.html#mapping-types-dict

To be a key in a dictionary, an object must be *hashable*. The spec for 
hashable objects is also in the documentation:

https://docs.python.org/3/glossary.html#term-hashable

In short, if a class implements __hash__() (which should never change 
during an object's lifetime) and __eq__(), it can be hashable.

Many python builtins are hashable, but mutable builtins aren't. For 
example lists aren't hashable.


To investigate a bit further, we might examine a particular example more 
closely. In the code snippet that follows, we make two tuples with the 
same data and two instances of a user-defined class with the same data. 
We make a dictionary and see the difference between using tuples as keys 
and instances of a user-defined class as keys.

```
tup1 = (1, 2)
tup2 = (1, 2)
d = dict()
d[tup1] = "one"
print(d[tup2])  # prints "one"
# Note that d "knows" tup1 and tup2 are "the same"

class myclass:
  def __init__(self):
    self.data = [1, 2]

myobj1 = myclass()
myobj2 = myclass()
print(myobj1.data == myobj2.data)  # True
d[myobj1] = "spam"
print(d[myobj2])  # raises KeyError as myobj2 not in dictionary
# d doesn't "know" that myobj1 and myobj2 are "the same"
```

This difference in behavior is due to the default __hash__ and __eq__ 
methods for myclass, which don't consider the attributes of each 
instance, whereas the hashing and comparison of tuples does consider the 
contents of the tuple.

- DLD

-- 
David Lowry-Duda <da...@lowryduda.com> <davidlowryduda.com>
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to