Search code examples
pythonstring-formattingpython-3.6f-string

f-string behaves differently then the format method for nested formatting


I am doing nested formatting using format and it doesn't work as expected. however if i try to do it with f-strings it works perfectly.

example:

doing this:

values = 'first', 'second', 'third'
a = f"""cardinality and values: {'|'.join(f'val:{val}, card:{i}'for i, val in enumerate(values))} """

gives me this (the needed result):

'cardinality and values: val:first, card:0|val:scond, card:1|val:third, card:2'

however if i try to do it using format:

a = """cardinality  and values: {'|'.join('val:{val}, card:{i}'.format(val=val, i=i) for i, val in enumerate(values))} """.format(values=values)

I get the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: "'|'"

how do i do this with format ?

I need to use format instead of f-strings because another file imports this string and then formats it.


Solution

  • format is just less powerful than f-strings, so you have to simplify the format string.

    Just get the comprehension from outside the format string:

    a = "cardinality  and values: {} ".format('|'.join('val:{val}, card:{i}'.format(val=val, i=i) for i, val in enumerate(values)))
    

    result:

    cardinality  and values: val:first, card:0|val:second, card:1|val:third, card:2 
    

    If you want to make a one-line "template", you could use a lambda:

    a = lambda v : "cardinality  and values: {} ".format('|'.join('val:{val}, card:{i}'.format(val=val, i=i) for i, val in enumerate(v)))
    

    now calling

    print(a(values))
    

    invokes the lambda which performs the formatting with the passed values. That's the closest to f-strings without f-strings that I can think of.