Python: 将旧样式格式模式转换为新样式格式模式

Python: convert old style formatting pattern to new style formatting pattern

是否有一些“内置”方法可以将旧样式格式模式字符串转换为新样式格式。或者最好只使用旧的正则表达式?

例如,我们有模式 '%(a)s - %(b)s' 并希望转换为 '{a} - {b}'

你可以使用 f-strings,只要确保你有 python3.6+

mystring = f'{a} - {b}'

未找到任何用于转换格式的内置 int 解决方案。这是我使用正则表达式实现的方式。

import re    

ODD_REPEAT_PATTERN = r'((?<!{c}){c}({c}{c})*(?!{c}))'
EVEN_REPEAT_PATTERN = r'(?<!{c})({c}{c})+(?!{c})'

def __to_new_format(fmt: str, named=True):
    def to_named_fmt(fmt):
        pattern = rf'{odd_perc_pattern}\((.*?)\)s'
        match = re.search(pattern, fmt)
        while match:
            # Only care about placeholder group here.
            __, __, placeholder = match.groups()
            fmt = fmt.replace(
                f'%({placeholder})s',
                f'{{{placeholder}}}'
            )
            match = re.search(pattern, fmt)
        return fmt

    def to_pos_fmt(fmt):
        even_perc_pattern = EVEN_REPEAT_PATTERN.format(c='%')
        pattern = rf'{even_perc_pattern}s'
        # When positional placeholder has even amount of percents, it
        # will be treated as not having enough arguments passed.
        if re.search(pattern, fmt):
            raise TypeError(
                'not all arguments converted during string formatting'
            )
        return fmt.replace('%s', '{}')

    odd_perc_pattern = ODD_REPEAT_PATTERN.format(c='%')
    # Escape `{` and `}`, because new formatting uses it.
    fmt = fmt.replace('{', '{{').replace('}', '}}')
    fmt = to_named_fmt(fmt) if named else to_pos_fmt(fmt)
    # If we find odd number of occurring percentage symbols, it means
    # those were not escaped and we can't finish conversion.
    if re.search(odd_perc_pattern, fmt):
        raise ValueError('incomplete format')
    return fmt.replace('%%', '%')


def to_new_named_format(fmt: str) -> str:
    """Convert old style named formatting to new style formatting.

    For example: '%(x)s - %%%(y)s' -> '{x} - %{y}'

    Args:
        fmt: old style formatting to convert.

    Returns:
        new style formatting.

    """
    return __to_new_format(fmt, named=True)


def to_new_pos_format(fmt: str) -> str:
    """Convert old style positional formatting to new style formatting.

    For example: '%s - %%%s' -> '{} - %{}'

    Args:
        fmt: old style formatting to convert.

    Returns:
        new style formatting.

    """
    return __to_new_format(fmt, named=False)