15

In Python 3.6, you can use f-strings like:

>>> date = datetime.date(1991, 10, 12)
>>> f'{date} was on a {date:%A}'
'1991-10-12 was on a Saturday'

I want to overload the method receiving the '%A' above. Can it be done?

For example, if I wanted to write a dumb wrapper around datetime, I might expect this overloading to look something like:

class MyDatetime:
    def __init__(self, my_datetime, some_other_value):
        self.dt = my_datetime
        self.some_other_value = some_other_value

    def __fstr__(self, format_str):
        return (
            self.dt.strftime(format_str) + 
            'some other string' +
            str(self.some_other_value
        )
Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
  • 1
    [Here's one I prepared earlier](https://gist.github.com/wimglenn/3186645d0474550160d3210bf488f8f8). – wim Nov 02 '17 at 18:05
  • 2
    for some more flexibility, you can override the methods made available in the [`string.Formatter` class](https://docs.python.org/3.4/library/string.html#string.Formatter) - such as `get_field`, `get_value`, `check_unused_args`, `format_field`, and `convert_field` - to get some more detailed control over the `format` function behavior. – Rick Nov 02 '17 at 18:23

1 Answers1

13

Yes, but by using __format__, not __fstr__.


f-strings were not an overhaul of the previous methods to format strings. Instead, it built on the protocols already in place.

From PEP 0498 that introduced them, in Code equivalence:

The exact code used to implement f-strings is not specified. However, it is guaranteed that any embedded value that is converted to a string will use that value's __format__ method. This is the same mechanism that str.format() uses to convert values to strings.

and then again, in Format Specifiers:

Once expressions in a format specifier are evaluated (if necessary), format specifiers are not interpreted by the f-string evaluator. Just as in str.format(), they are merely passed in to the __format__() method of the object being formatted.

So, there's no new special method for them. You need to define a __format__ method that takes the spec and returns an appropriately formatted string.

As the docs on __format__ also describe:

Called by the format() built-in function, and by extension, evaluation of formatted string literals and the str.format() method, to produce a “formatted” string representation of an object.

Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253