partial string formatting

前端 未结 21 1023
野的像风
野的像风 2020-11-28 04:30

Is it possible to do partial string formatting with the advanced string formatting methods, similar to the string template safe_substitute() function?

F

21条回答
  •  时光取名叫无心
    2020-11-28 04:59

    This limitation of .format() - the inability to do partial substitutions - has been bugging me.

    After evaluating writing a custom Formatter class as described in many answers here and even considering using third-party packages such as lazy_format, I discovered a much simpler inbuilt solution: Template strings

    It provides similar functionality but also provides partial substitution thorough safe_substitute() method. The template strings need to have a $ prefix (which feels a bit weird - but the overall solution I think is better).

    import string
    template = string.Template('${x} ${y}')
    try:
      template.substitute({'x':1}) # raises KeyError
    except KeyError:
      pass
    
    # but the following raises no error
    partial_str = template.safe_substitute({'x':1}) # no error
    
    # partial_str now contains a string with partial substitution
    partial_template = string.Template(partial_str)
    substituted_str = partial_template.safe_substitute({'y':2}) # no error
    print substituted_str # prints '12'
    

    Formed a convenience wrapper based on this:

    class StringTemplate(object):
        def __init__(self, template):
            self.template = string.Template(template)
            self.partial_substituted_str = None
    
        def __repr__(self):
            return self.template.safe_substitute()
    
        def format(self, *args, **kws):
            self.partial_substituted_str = self.template.safe_substitute(*args, **kws)
            self.template = string.Template(self.partial_substituted_str)
            return self.__repr__()
    
    
    >>> s = StringTemplate('${x}${y}')
    >>> s
    '${x}${y}'
    >>> s.format(x=1)
    '1${y}'
    >>> s.format({'y':2})
    '12'
    >>> print s
    12
    

    Similarly a wrapper based on Sven's answer which uses the default string formatting:

    class StringTemplate(object):
        class FormatDict(dict):
            def __missing__(self, key):
                return "{" + key + "}"
    
        def __init__(self, template):
            self.substituted_str = template
            self.formatter = string.Formatter()
    
        def __repr__(self):
            return self.substituted_str
    
        def format(self, *args, **kwargs):
            mapping = StringTemplate.FormatDict(*args, **kwargs)
            self.substituted_str = self.formatter.vformat(self.substituted_str, (), mapping)
    

提交回复
热议问题