subclass string.Formatter

后端 未结 2 1920
长情又很酷
长情又很酷 2021-01-18 22:39

Following a remark here: How to define a new string formatter, I tried subclassing string.Formatter. Here is what I\'ve done. Unfortunately I seem to have broke

相关标签:
2条回答
  • 2021-01-18 23:09

    str.format does auto numbering, while string.Formatter does not.

    Modifying __init__ and overriding get_value will do the trick.

    def __init__(self):
        super(CustFormatter, self).__init__()
        self.last_number = 0
    
    def get_value(self, key, args, kwargs):
        if key == '':
            key = self.last_number
            self.last_number += 1
        return super(CustFormatter, self).get_value(key, args, kwargs)
    

    BTW, above code does not strictly mimic str.format behavior. str.format complains if we mix auto numbering with manual number, but above does not.

    >>> '{} {1}'.format(1, 2)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: cannot switch from automatic field numbering to manual field specification
    >>> '{0} {}'.format(1, 2)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: cannot switch from manual field specification to automatic field numbering
    
    0 讨论(0)
  • 2021-01-18 23:26

    Good news: you have not done anything wrong. Bad news: that's how string.Formatter behaves, it does not support {}-like positional format. So, the last call will fail even without any subclassing. Good news: that's can be fixed by overriding the parse method:

    import string
    
    class CF(string.Formatter):
        def parse(self, s):
            position = 0
            for lit, name, spec, conv in super(CF, self).parse(s):
                if not name:
                    name = str(position)
                    position += 1
                yield lit, name, spec, conv
    

    Bad news... Ah, no, that's basically it:

    >>> CF().format('{} {}!', 'Hello', 'world')
    'Hello world!'
    
    0 讨论(0)
提交回复
热议问题