Overriding definitions for mutable objects
This example will continue using the Cards
class. The idea of mutable cards is strange, perhaps even wrong. However, we'd like to apply just one small tweak to the previous examples.
The following is a class hierarchy that provides us with the definitions of __hash__()
and __eq__()
, appropriate for mutable objects:
class Card3: insure= False def __init__( self, rank, suit, hard, soft ): self.rank= rank self.suit= suit self.hard= hard self.soft= soft def __repr__( self ): return "{__class__.__name__}(suit={suit!r}, rank={rank!r})".format(__class__=self.__class__, **self.__dict__) def __str__( self ): return "{rank}{suit}".format(**self.__dict__) def __eq__( self, other ): return self.suit == other.suit and self.rank == other.rank # and self.hard == other.hard and self.soft == other.soft __hash__ = None class AceCard3( Card3 ): insure= True def __init__( self, rank, suit ): super().__init__( "A", suit, 1, 11 )
Let's see how objects of these classes behave. We expect them to compare as equal but not work at all with sets or dictionaries. We'll create two objects as follows:
>>> c1 = AceCard3( 1, '♣' ) >>> c2 = AceCard3( 1, '♣' )
We've defined two instances of what appear to be the same card.
We'll look at their ID values to ensure they really are distinct:
>>> print( id(c1), id(c2) ) 4302577040 4302577296
No surprise here. We'll see if we can get hash values:
>>> print( hash(c1), hash(c2) ) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'AceCard3'
As __hash__
is set to None
, these Card3
objects can't be hashed and can't provide a value for the hash()
function. This is the expected behavior.
We can perform equality comparisons, though, as shown in the following code snippet:
>>> print( c1 == c2 ) True
The equality test works properly, allowing us to compare cards. They just can't be inserted into sets or used as a key to a dictionary.
The following is what happens when we try:
>>> print( set( [c1, c2] ) ) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'AceCard3'
We get a proper exception when trying to put these into a set.
Clearly, this is not a proper definition for something that—in real life—is immutable like a card. This style of definition is more appropriate for stateful objects such as Hand
, where the content of the hand is always changing. We'll provide you with a second example of stateful objects in the following section.