[Python-Dev] summary of transitioning from % to {} formatting (original) (raw)
Steven D'Aprano steve at pearwood.info
Sat Oct 3 20:01:56 CEST 2009
- Previous message: [Python-Dev] summary of transitioning from % to {} formatting
- Next message: [Python-Dev] summary of transitioning from % to {} formatting
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On Sun, 4 Oct 2009 01:41:36 am Steven Bethard wrote:
I thought it might be useful for those who don't have time to read a million posts to have a summary of what's happened in the formatting discussion.
The basic problem is that many APIs in the standard library and elsewhere support only %-formatting and not {}-formatting, e.g. logging.Formatter accepts:: logging.Formatter(fmt="%(asctime)s - %(name)s") but not:: logging.Formatter(fmt="{asctime} - {name}")
Why is this a problem? Is it because the APIs require extra functionality that only {} formatting can provide? Possibly, but I doubt it -- I expect that the reason is:
(1) Some people would like to deprecate % formatting, and they can't while the std lib uses % internally.
(2) Some APIs in the std lib are tightly coupled to their internal implementation, and so you can't change their implementation without changing the API as well.
Remove either of these issues, and the problem becomes a non-problem, and no action is needed. Personally, I'd like to see no further talk about deprecating % until at least Python 3.2, that is, the earliest we would need to solve this issue would be 3.3. As the Zen says, "Although never is often better than right now."
There seems to be mostly agreement that these APIs should at least support both formatting styles, and a sizable group (including Guido) believe that %-formatting should eventually be phased out (e.g. by Python 4).
-1 on that. Time will tell if I change my mind in a couple of years, but I suspect not -- for simple formatting, I far prefer %. Judging by the reaction on comp.lang.python when this has been discussed in the past, I think a large (or at least loud) proportion of Python programmers agree with me.
There are a number of competing proposals on how to allow such APIs to start accepting {}-format strings:
* Add a parameter which declares the type of format string:: logging.Formatter(fmt="{asctime} - {name}", format=BRACES) The API code would then switch between %-format and {}-format based on the value of that parameter. If %-formatting is to be deprecated, this could be done by first deprecating format=PERCENTS and requiring format=BRACES, and then changing the default to format=BRACES.
+0.5
* Create string subclasses which convert % use to .format calls:: __ = bracefmt_ logging.Formatter(fmt=("{asctime} - {name}"))_
There are a few problems with this approach:
Nobody has yet demonstrated that this brace_fmt class is even possible. It should be easy to handle a restricted set of simple templates (e.g. of the form "%(name)s" only), but what of the full range of behaviour supported by % formatting?
Even if it is doable, it is a wrapper class, which means the module will suffer a performance hit on every call. At this time, we have no idea what the magnitude of that hit will be, but .format() is already slower than % so it will likely be significant.
It strikes me as hideously ugly. I for one would delay using it as long as possible, no matter how many DepreciationWarnings I got. I'd drag my feet and avoid changing and complain loudly and then become sullen and resentful when I couldn't avoid making the change. I'd much rather go straight from %-based templates to {} in a single step than have this Frankenstein monster intermediate.
[...]
* Teach the API to accept callables as well as strings:: logging.Formatter(fmt="{asctime} - {name}".format) The API code would just call the object with .format() style arguments if a callable was given instead of a string.
+0.5
* Create translators between %-format and {}-format:: assert tobraces("%(asctime)s") == "{asctime}" assert topercents("{asctime}") == "%(asctime)s"
+1, assuming such translators are even possible. Being optimistic, such translators would have one additional benefit: they would enable modules to completely decouple the API they offer from their internal implementation, without paying a runtime cost on every call, just a single once-off translation at initialisation time.
In theory, this could mean that modules could, if they choose, continue to offer an API based on % long after str.mod is removed from the language.
-- Steven D'Aprano
- Previous message: [Python-Dev] summary of transitioning from % to {} formatting
- Next message: [Python-Dev] summary of transitioning from % to {} formatting
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]