I was also confused by the expression evaluation thing. Reading between the lines, it seems like
logger.debug("hello %s", foo)
may be better than logger.debug(f"hello {foo}")
in the case when loglevel is higher than debug. In the first version, the final string does not have to be computed, while in the second version, we might construct the string and then do nothing since the loglevel is excluded.