When formatting a complex object that includes a collection, we have two formatting issues: how to format the overall object and how to format the items in the collection. When we look at Hand, for example, we see that we have a collection of individual Cards objects. We'd like to have Hand delegate some formatting details to the individual Card instances in the Hand collection.
The following is a __format__() method that applies to Hand:
def __format__(self, spec: str) -> str:
if spec == "":
return str(self)
return ", ".join(f"{c:{spec}}" for c in self.cards)
The spec parameter will be used for each individual Card instance within the Hand collection. f-string f"{c:{spec}}" uses the nested format specification technique to push the spec string into the format. This creates a final format, which will be applied to each Card instance.
Given this method, we can format a Hand object, player_hand, as follows:
>>> d = Deck()
>>> h = Hand(d.pop(), d.pop(), d.pop())
>>> print("Player: {hand:%r%s}".format(hand=h))
Player: K♦, 9♥
This string in the print() function used the format() method of the Hand object. This passed the %r%s format specification to each Card instance of the Hand object to provide the desired formatting for each card of the hand.