Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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')
like image 994
mfurseman Avatar asked Aug 20 '19 08:08

mfurseman


People also ask

How do you custom format a cell in Excel with text and numbers?

Select a cell for which you want to create custom formatting, and press Ctrl+1 to open the Format Cells dialog. Under Category, select Custom. Type the format code in the Type box. Click OK to save the newly created format.


1 Answers

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
like image 161
jdehesa Avatar answered Sep 27 '22 15:09

jdehesa