Skip to content

← Pattern Matching, f-Strings and Newer Syntax step 3 of 23

Medium Primitives

Give a Class Its Own Format Codes

Your job runner stores how long each job took as a Duration of whole seconds. Different screens show it in different ways:

took = Duration(3725)
print(f"{took}")        # 1:02:05
print(f"{took:short}")  # 1h 2m 5s
print(f"{took:,d}")     # 3,725

When Python formats a value in an f-string, it calls the value's __format__ method. The argument is the format spec, the text after the colon, as a string. f"{took:short}" calls took.__format__("short"), and a plain f"{took}" passes the empty string "". Built-in types read specs such as ,d and .2f. Your own class can accept any words you choose.

What to write

Fill in two methods of Duration. In h:mm:ss below, h, m and s stand for the hours, minutes and seconds in self.seconds. Hours do not roll over into days.

__format__(self, spec) handles four kinds of spec:

  • For "", return h:mm:ss, with minutes and seconds always two digits, as in "1:02:05" or "25:01:01".
  • For "short", return a form such as "1h 2m 5s". Leave out hours when they are 0, and leave out minutes too when both are 0. So 125 seconds is "2m 5s", 5 seconds is "5s", 0 seconds is "0s", and 3600 seconds is "1h 0m 0s".
  • For a spec that ends in d, return the number of seconds formatted with that spec, by passing it on with format(self.seconds, spec). So ,d gives "3,725" and >6d gives " 3725".
  • For any other spec, raise ValueError.

A spec that ends in d but that int cannot read, such as dd, makes format raise ValueError itself. You do not need to catch it.

__str__(self) returns the same text as f"{self}". If you write only __format__, f"{took}" works, but print(took) and str(took) ignore __format__ and show the default <__main__.Duration object at 0x...>.

The tests use whole seconds of 0 or more.

What the driver checks

Keep solve as it is. It returns:

  • plain: f"{d}" for each duration.
  • text: str(d) for each duration.
  • styled: f"{d:{spec}}" for each duration.
  • error: "", or "ValueError" if __format__ rejected the spec. Then styled is empty.

With no durations, solve formats nothing, so even a bad spec gives an empty styled list and an empty error.