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

Creating immutable objects as a tuple subclass

We can also create an immutable object by making our Card property a subclass of tuple and an override to __getattr__(). In this case, we'll translate __getattr__(name) requests to self[index] requests. As we'll see in Chapter 6, Creating Containers and Collections, self[index] is implemented by __getitem__(index).

The following is a small extension to the built-in tuple class:

class BlackJackCard2( tuple ):
    def __new__( cls, rank, suit, hard, soft ):
        return super().__new__( cls, (rank, suit, hard, soft) )
    def __getattr__( self, name ):
        return self[{'rank':0, 'suit':1, 'hard':2 , 'soft':3}[name]]
    def __setattr__( self, name, value ):
        raise AttributeError

In this example, we simply raised a simple AttributeError exception rather than providing detailed error messages.

When we use the preceding code, we see the following kinds of interaction:

>>> d = BlackJackCard2( 'A', '♠', 1, 11 )
>>> d.rank
'A'
>>> d.suit
'♠'
>>> d.bad= 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in __setattr__AttributeError

We can't change the value of a card easily. However, we can still tweak d.__dict__ to introduce additional attributes.