Nested f-strings

Python Programming

Question or problem about Python programming:

Thanks to David Beazley’s tweet, I’ve recently found out that the new Python 3.6 f-strings can also be nested:

>>> price = 478.23
>>> f"{f'${price:0.2f}':*>20s}"
'*************$478.23'

Or:

>>> x = 42
>>> f'''-{f"""*{f"+{f'.{x}.'}+"}*"""}-'''
'-*+.42.+*-'

While I am surprised that this is possible, I am missing on how practical is that, when would nesting f-strings be useful? What use cases can this cover?

Note: The PEP itself does not mention nesting f-strings, but there is a specific test case.

How to solve the problem:

Solution 1:

I don’t think formatted string literals allowing nesting (by nesting, I take it to mean f'{f".."}') is a result of careful consideration of possible use cases, I’m more convinced it’s just allowed in order for them to conform with their specification.

The specification states that they support full Python expressions* inside brackets. It’s also stated that a formatted string literal is really just an expression that is evaluated at run-time (See here, and here). As a result, it only makes sense to allow a formatted string literal as the expression inside another formatted string literal, forbidding it would negate the full support for Python expressions.

The fact that you can’t find use cases mentioned in the docs (and only find test cases in the test suite) is because this is probably a nice (side) effect of the implementation and not it’s motivating use-case.


Actually, with two exceptions: An empty expression is not allowed, and a lambda expression must be surrounded by explicit parentheses.

Solution 2:

I guess this is to pass formatting parameters in the same line and thus simplify f-strings usage.

For example:

>>> import decimal
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal("12.34567")
>>> f"result: {value:{width}.{precision}}"
'result:      12.35'

Of course, it allows programmers to write absolutely unreadable code, but that’s not the purpose 🙂

Solution 3:

I’ve actually just come across something similar (i think) and thought i’d share.

My specific case is a big dirty sql statement where i need to conditionally have some very different values but some fstrings are the same (and also used in other places).

Here is quick example of what i mean. The cols i’m selecting are same regardless (and also used in other queries elsewhere) but the table name depends on the group and is not such i could just do it in a loop.

Having to include mycols=mycols in str2 each time felt a little dirty when i have multiple such params.

I was not sure this would work but was happy it did. As to how pythonic its is i’m not really sure tbh.

mycols='col_a,col_b'

str1 = "select {mycols} from {mytable} where group='{mygroup}'".format(mycols=mycols,mytable='{mytable}',mygroup='{mygroup}')

group = 'group_b'

if group == 'group_a':
    str2 = str1.format(mytable='tbl1',mygroup=group)
elif group == 'group_b':
    str2 = str1.format(mytable='a_very_different_table_name',mygroup=group)

print(str2)

Solution 4:

Working on a pet project I got sidetracked by writing my own DB library. One thing I discovered was this:

>>> x = dict(a = 1, b = 2, d = 3)
>>> z = f"""
    UPDATE TABLE 
        bar 
    SET 
        {", ".join([ f'{k} = ?'     for k in x.keys() ])} """.strip()
>>> z
'UPDATE TABLE 
    bar 
SET 
    a = ?, b = ?, d = ?  '

I was also surprised by this and honestly I am not sure I would ever do something like this in production code BUT I have also said I wouldn’t do a lot of other things in production code.

Solution 5:

Any basic use case is where you need a string to completely describe the object you want to put inside the f-string braces {}. For example, you need strings to index dictionaries.

So, I ended up using it in an ML project with code like:

scores = dict()
scores[f'{task}_accuracy'] = 100. * n_valid / n_total
print(f'{task}_accuracy: {scores[f"{task}_accuracy"]}')

Solution 6:

I found nesting to be useful when doing ternaries. Your opinion will vary on readability, but I found this one-liner very useful.

logger.info(f"No program name in subgroups file. Using {f'{prg_num} {prg_orig_date}' if not prg_name else prg_name}")

As such, my tests for nesting would be:

  • Is the value reused? (Variable for expression re-use)
  • Is the expression clear? (Not exceeding complexity)

Solution 7:

You could use it for dynamicism. For instance, say you have a variable set to the name of some function:

func = 'my_func'

Then you could write:

f"{f'{func}'()}" 

which would be equivalent to:

'{}'.format(locals()[func]()) 

or, equivalently:

'{}'.format(my_func())

Hope this helps!