Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
How to override default string formatter?
It is possible to create a new formatter class by subclassing string.Formatter
class and then to use it like myformatter.format("{foo:customformat}", foo=foo)
. It's not super-convenient though, and above all, it fails miserably with f-strings, i.e. f"{foo:customformat}"
won't use my custom formatter class.
I also tried to subclass str
and override the .format()
method, but it still won't cut for f-strings.
1 answer
The following users marked this post as Works for me:
User | Comment | Date |
---|---|---|
luser | (no comment) | May 5, 2023 at 10:26 |
Python doesn't support extending the mechanics of how f-strings are parsed; the reference doesn't give the specific mechanism, but it doesn't say that there's any connection between the parsing of f-strings and other formatting tools like string.Formatter
, other than a superficial use of the same formatting mini-language.
What f-strings are specified to do is to concatenate all of the literal string bits with appropriately formatted expressions. If you want to change how an individual expression is formatted, you can do that by overriding __format__
on your values or wrapping a value with a class having a custom __format__
:
>>> class Wrapper:
... def __init__(self, value):
... self.value = value
... def __format__(self, format_spec):
... if format_spec == 'customformat':
... return '!!!'
... return format(self.value, format_spec)
...
>>> f"-- {Wrapper(42)} --"
'-- 42 --'
>>> f"-- {Wrapper(42):customformat} --"
'-- !!! --'
But you can't fundamentally change the way that f-strings get parsed, the way that you can with a string.Formatter
subclass; nor can you change the run-time behavior of an f-string to automatically wrap all of the incoming expressions, for example. (It may be possible to do this in a particular Python implementation, but CPython's code doesn't seem to allow it, and it certainly wouldn't be guaranteed to work across any other implementation. CPython parses the internals of f-strings at the same time as it parses the rest of your code, so there is no opportunity to override that behavior.)
0 comment threads