Mastering Objectoriented Python
上QQ阅读APP看书,第一时间看更新

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.