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

Collection __str__() and __repr__()

When there's a collection involved, we need to format each individual item in the collection as well as the overall container for those items. The following is a simple collection with both __str__() and __repr__() methods:

class Hand:
    def __init__( self, dealer_card, *cards ):
        self.dealer_card= dealer_card
        self.cards= list(cards)
    def __str__( self ):
        return ", ".join( map(str, self.cards) )
    def __repr__( self ):
        return "{__class__.__name__}({dealer_card!r}, {_cards_str})".format(
        __class__=self.__class__,
        _cards_str=", ".join( map(repr, self.cards) ),
        **self.__dict__ )

The __str__() method is a simple recipe, as follows:

  1. Map str() to each item in the collection. This will create an iterator over the resulting string values.
  2. Use ", ".join() to merge all the item strings into a single, long string.

The __repr__() method is a multiple-part recipe, as follows:

  1. Map repr() to each item in the collection. This will create an iterator over the resulting string values.
  2. Use ", ".join() to merge all the item strings.
  3. Create a set of keywords with __class__, the collection string, and the various attributes from __dict__. We've named the collection string _cards_str so that it doesn't conflict with an existing attribute.
  4. Use "{__class__.__name__}({dealer_card!r}, {_cards_str})".format() to combine the class name and the long string of item values. We use the !r formatting to ensure that the attribute uses the repr() conversion too.

In some cases, this can be optimized and made somewhat simpler. Use of positional arguments for the formatting can somewhat shorten the template string.