mfurseman
mfurseman

Reputation: 1028

How to provide custom formatting from format string?

I can use a custom class to extend Python's string formatting:

class CaseStr(str):
    def __format__(self, fmt):
        if fmt.endswith('u'):
            s = self.upper()
            fmt = fmt[:-1]
        elif fmt.endswith('l'):
            s = self.lower()
            fmt = fmt[:-1]
        else:
            s = str(self)
        return s.__format__(fmt)

I can then use this class to format arguments which are passed to a strings format method:

unformatted_string = 'uppercase: {s:u}, lowercase: {s:l}'
print unformatted_string.format(s=CaseStr('abc'))

While this works it seems awkward that the custom format specifier is in the base string, but the arguments passed to it's format method are actually responsible for parsing the format specifier.

Is there a way to place the knowledge required to interpret the custom string within the base string itself?

class CaseStrWrapper(str):
    ...

unformatted_string = CaseStrWrapper('uppercase: {s:u}, lowercase: {s:l}')
print unformatted_string.format(s='abc')

Upvotes: 9

Views: 7628

Answers (1)

javidcf
javidcf

Reputation: 59741

You would normally use custom string formatting for that (see PEP 3101). For your case, you could have something like this:

import string

class MyFormatter(string.Formatter):
    def format_field(self, value, format_spec):
        if isinstance(value, str):
            if format_spec.endswith('u'):
                value = value.upper()
                format_spec = format_spec[:-1]
            elif format_spec.endswith('l'):
                value = value.lower()
                format_spec = format_spec[:-1]
        return super(MyFormatter, self).format(value, format_spec)

fmt = MyFormatter()
print(fmt.format('uppercase: {s:u}, lowercase: {s:l}', s='abc'))
# uppercase: ABC, lowercase: abc

Upvotes: 9

Related Questions