
Serhiy Storchaka writes:
Currently format strings (and f-string expressions) support three conversions: !s -- str, !r -- repr and !a for ascii.
It's not clear to me what these are good for, to be honest. Why not just have s, r, and a format codes? The !conversions don't compose with format codes: >>> f"{10!r:g}" Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: Unknown format code 'g' for object of type 'str' So I don't think I want to go further. I have some sympathy for your proposal, in part because I'd like to see something done about moving I18N into the format() mechanism. But I'm going to play devil's advocate, mostly because I'm getting old enough to not like change so much. ;-)
I propose to add support of additional conversions: for int, float and operator.index. It will help to convert automatically printf- like format strings to f-string expressions: %d, %i, %u -- use int, %f -- use float, %o, %x -- use operator.index.
This makes more sense to me than !s, !r, and !a -- you might or might not want these conversions, I guess. But it seems like a lot of complexity to add. On the other hand, isn't the answer "fix __format__ in class definitions?" For example, currently >>> for i in "befgodxs": ... print(format(10, i)) ... 1010 1.000000e+01 10.000000 10 12 10 a Traceback (most recent call last): File "<stdin>", line 2, in <module> ValueError: Unknown format code 's' for object of type 'int' But we could change int.__format__ to allow 's' as a format code[1], automagically calling str(), just as 'efg' are allowed and automagically call float().
Currently I write f"path = {repr(str(path))}" or f"path = {str(path)!r}", but want to write f"path = {path!s!r}".
I have some sympathy for this; it's not a big change, and given the syntax you propose I doubt anyone would be confused about the semantics, including the order of conversions. However: To me, this seems like a clear case where you want to embed the conversions in the format code mechanism for those specific types: extend the __format__ method for URL objects to allow {url:h} where the 'h' format code applies "hex-escape", or you could repurpose the "u" code from the standard minilanguage to apply url-escape, or (I don't know if format allows) you could use {url:%}! How many types would need an additional format code to handle whatever use case wants repr(str())? Or are you envisioning heavy use of !f!a etc? (I can't see how any of the existing conversions could have an effect on the output of the numerical conversions you propose, though.)
Do we need support of more standard conversions?
I don't know about conversions, but somehow getting I18N substitutions into format so we could eventually allow Americans to "def _()" again! I know, I18N is hard, but isn't that the Holy Grail? {date_time!p} ('p' for "POSIX locale"), anyone? I think !!conversions might be useful if we could find a way to move I18N substitutions into the format mechanism, though. At the very least, {currency!p!a} might be used frequently. One thing: I18N is likely to eat up most of the ISO 8859 repertoire for conversion codes. Just consider the number of variations on ISO 8601 datetime formatting, let alone the scads of other variations on datetimes, and the other POSIX substitutions.
Do we want to support custom conversions (registered globally as encodings and error handlers). re.escape, html.escape and shlex.quote could be very useful in some applications.
This really seems to me to be the kind of thing that should be handled in __init__ whenever possible, and __format__ if not. Footnotes: [1] I recognize this may imply many changes, since some (all?) of the builtin types seem to be supported by object.__format__.