How to convert ordinary string to an f-string or evaluate an ordinary string as an f-string?

At this month's COhPy meeting, someone asked how to either convert an ordinary string to an f-string or evaluate an ordinary string as an f-string.

One solution is to use eval() as shown below. What other solutions are there?

Why was %r used instead of %s or %a in the first eval expression?


In [1]:
date_formats = {
    'iso': '{year}-{month:02d}-{day:02d}',
    'us': '{month}/{day}/{year}',
    'other': '{day} {month} {year}',
}
dates = (
    (2017, 3, 27),
    (2017, 4, 24),
    (2017, 5, 22),
)

for format_name, format in date_formats.items():
    print(f'{format_name}:')
    for year, month, day in dates:
        print(eval('f%r' % format))


iso:
2017-03-27
2017-04-24
2017-05-22
us:
3/27/2017
4/24/2017
5/22/2017
other:
27 3 2017
24 4 2017
22 5 2017

One surprise for me is that this is another way of deferring evaluation of f-strings, and that it is easier to read than using lambdas. I wonder how much slower eval() is than using the lambdas.

Which of the following is easier for you read? Why/how?

print(eval('f%r' % format))
print(eval(f'f{format!r}'))

I wonder what sympy thinks of manipulating f-strings.