
Serhiy Storchaka writes:
Because it converts value to string, and string formatting does not support "g". Converters !s, !r and !a are separated from format specifier, and it is old and widely used feature.
And poorly documented, IMO. I'll see if I can do better.
but if we are going to make this feature public, it is worth to discuss it ahead to avoid name conflicts in future. I asked what letters should be chosen for convertors for int() and index().
I would go with !f for "float", !d for "decimal" (int) and !x or !i for "index". I like !x better because of the ambiguity of "i". But I don't think I'm likely to use any of them, so that's about +0.2 for all of them.
I am not sure which relation does it have to I18N.
First, the use of "_()" as the localizable string marker conflicts with the common use of "_" as a "throwaway" identifier. Second, POSIX locale lookup (and possibly gettext, too) seems like a very obvious candidate for !conversion before formatting a string field, similar to casting a number to float for e, f, or g formatting.
We need to format a value as integer or float independently from __format__ implementation, and raise an error if it cannot be converted to integer or float. The purpose of the feature is bypassing __format__ and get the same result as in printf-style formatting.
Surely you don't mean "bypass format"? If you bypass format, how do you select among e, f, and g? This is exactly the confusion that caused me trouble: the use cases for !s, !r, and !a generally do bypass __format__ (but something like "x!r:>10" is occasionally useful and does work). So at the language level they appear to be syntactic sugar, since they are not programmable (see Cameron Simpson's posts).
Yes, we could add support for "s" in int.__format__, but it was decided to not do this for some reasons.
I'm not really suggesting that we do this *now*, since the backward incompatibility is horrifying. I'm asking why converters were exposed in the first place since they look like syntactic suger. I guess the basic answer is "they're already needed for int -> float conversion, and they're nice abbreviations for str(), repr(), and ascii() because format() and friends don't allow function calls in {}". Anyway, I'm satisfied with that, you don't need to convince me.
Supporting the "h" format code in the __format__ method for URL objects is a reasonable idea, and it is the purpose of __format__ methods. But it does not relates to converters. If you want to dump the value of some variable using repr(), do you want to add support of "r" in every implementation of __format__ in the world (and what if some is not support it or use it with different semantic)? "%r" % x just calls repr(), and we wanted this feature in new formatting.
You could have it if the format codes 's', 'r', and 'a' were implemented in the formatting mechanisms, i.e., in print() itself, in format(), in str.format, and in f-strings. I'm not ready to argue for changing it now, but I think it would have been better if format specs included the preprocessor !conversion and also a postprocessor (for Cameron), and maybe allowed those to be programmable via a mapping of codes to type converters for the preprocessor and a mapping of codes to str -> str functions for the postprocessor, or passed these to __format__ as a triple (format_spec, pre_code, post_code). Steve