[Python-Dev] transitioning from % to {} formatting

Brett Cannon brett at python.org
Thu Oct 1 20:03:39 CEST 2009


On Thu, Oct 1, 2009 at 06:29, Vinay Sajip <vinay_sajip at yahoo.co.uk> wrote:
> Paul Moore <p.f.moore <at> gmail.com> writes:
>
>> This seems to me to be almost the same as the previous suggestion of
>> having a string subclass:
>>
>> class BraceFormatter(str):
>>     def __mod__(self, other):
>>         # Needs more magic here to cope with dict argument
>>         return self.format(*other)
>>
>> __ = BraceFormatter
>>
>> logger.debug(__("The {0} is {1}"), "answer", 42)
>>

So I created this last night:

import collections

class braces_fmt(str):

    def __mod__(self, stuff):
        if isinstance(stuff, tuple):
            return self.__class__(self.format(*stuff))
        elif isinstance(stuff, collections.Mapping):
            return self.__class__(self.format(**stuff))
        else:
            return self.__class__(self.format(stuff))

The biggest issue is that ``"%s" % {'a': 42}`` substitutes the dict
instead of throwing an error that str.format() would do with the code
above. But what's nice about this is I think I can use this now w/ any
library that expects % interpolation and it should basically work.

>> The only real differences are
>>
>> 1. The positioning of the closing parenthesis
>> 2. The internal implementation of logger.debug needs to preserve
>> string subclasses properly
>>
>
> The other difference is that my suggestion supports Barry's desire to use
> string.Template with no muss, no fuss ;-)

I don't think Paul's suggestion requires much more work to support
string.Template, simply a subclass that implements __mod__>

> Plus, very little additional work is
> required compared to your items 1 and 2. ISTM BraceMessage would be something
> like this,
>
> clsss BraceMessage:
>    def __init__(self, fmt, *args, **kwargs):
>        self.fmt = fmt
>        self.args = args
>        self.kwargs = kwargs
>
>    def __str__(self):
>        return self.fmt.format(*self.args, **self.kwargs)

I guess my question is what's the point of the class if you are simply
converting it before you pass it in to the logger? To be lazy about
the formatting call? Otherwise you could simply call str.format() with
your arguments before you pass the string into the logger and not have
to wrap anything.

-Brett


More information about the Python-Dev mailing list