Cameron Simpson writes:
First up, I have somehow missed this (":format_name") in the semirecursive mess which is the python format-and-friends descriptions. (object.__format__? str.format? str.formap_map? f''? the format mini-language? all in separate places, for reasonable reasons, but my head has exploded multiple times trying to stitch them together).
Agreed on the doc. I'm going to try to do something about that, but it may take a while.
The "!r" conversion is applied _by_ the formatting, _to_ an arbitrary value. So I could write a single function for my hypothetical "!lc" which did what I want for an arbitrary object, because it would be called with the value being converted.
True. Which works if all you want to do is convert the object. But this requires that you do all the work in your hypothetical "!lc", which does not take parameters other than the value it converts, and does not have access to the format specification.
By contrast, the ":lc" format specifier form requires the value being formatted _itself_ to have a special __format__ method. This scales poorly when I might put almost anything into the format string.
I don't understand what you're talking about. As you point out yourself:
The ":lc" approach:
The problem with __format__ is that it must be applied to a class. The values inside {foo.bar.zot} in the format string might be almost any type. The only way to get __format__ to do what I'd like is to wrap every such value in a proxy of some kind with a .__format__ method.
Sure. That's exactly what LowerableStr does, and it's very general, since it has access to both the value and the format spec, and can do both preprocessing of the value and postprocessing of the formatted string. The !conversion approach really is basically a cast, the internal function that does the conversion takes the object to be converted and a code (a str, possibly just a single character).
So to my mind, being able to plug in a mapping of additional (or overriding) conversion specifiers would be the most natural way to improve my situation.
I can see why you would want it for this particular application, but I'm not yet persuaded it's general enough to worth making this aspect of Python user-configurable when there's another way to do it already. In particular, although *you* won't use it to allow users to invoke arbitrary functions, there's no reason it couldn't be used that way, as __format__ already can. I don't think it's a good idea to introduce more places to execute arbitrary code even as a purely theoretical matter. "Although practicality beats purity," of course, but that's my current opinion.
Architecturally, that is where I would want my magic "lc" et al to land. I could move the magic "._meta" attribute in there as well producing fewer "magic" attributes, etc.
I don't see why you couldn't get the same benefits from the __format__ approach. The main thing difference I see with the __format__ approach is that you do need a proxy object in general (if __format__ is mutable, I don't think you do although I haven't tried it). But you'd only have to write it once, and in the event someone did want to use the original __format__ and format spec in post-processing the resulting string, it would be right there. Steve