Search code examples
pythonf-string

What benefits does the % formatter offer in comparison to f strings?


I was going through the fluent python book when I came across the following code

def tag(name, *content, cls=None, **attrs):
    """Generate one or more HTML tags"""
    if cls is not None:
        attrs['class'] = cls
    if attrs:
        attr_str = ''.join(' %s="%s"' % (attr, value)
    for attr, value
        in sorted(attrs.items()))
    else:
        attr_str = ''
    if content:
        return '\n'.join('<%s%s>%s</%s>' %
                         (name, attr_str, c, name) for c in content)
    else:
        return f'<{name}{attr_str} />'

Since this book was introduced prior to f-strings, I thought I could make the following replacement

    if content:
        return '\n'.join(f'<{name}{attr_str}>{[c for c in content]}<{name}>') 

This returns each character on a new line. Rather than the desired output: '<p>hello</p>'

Is the % formater necessary here? Can this output be achieved using a list comprehension?


Solution

  • Instead of

    '<%s%s>%s</%s>' % (name, attr_str, c, name)
    

    you can use

    f'<{name}{attr_str}>{c}</{name}>'
    

    so finally you will have generator

    f'<{name}{attr_str}>{c}<{name}>' for c in content
    

    instead of

    '<%s%s>%s</%s>' % (name, attr_str, c, name) for c in content
    

    and

    return '\n'.join( f'<{name}{attr_str}>{c}<{name}>' for c in content )
    

    You can also use [] to create list comprehension and use print() to see all created elements before it uses them in join()

    data = [ f'<{name}{attr_str}>{c}<{name}>' for c in content ]
    print(data)
    return "\n".join( data )