crates/ruff_linter/resources/mdtest/pyupgrade/f-string.md
f-string (UP032)lint.select = ["UP032"]
A str.format argument is evaluated once, but an f-string re-evaluates it on every interpolation. So
when an argument is used more than once and can have a side effect, the call is left unconverted to
avoid running that side effect twice. This used to cover only call expressions; it now covers any
side-effecting expression, such as a subscript or a walrus binding. Even a builtin call like list()
counts, since the f-string would construct a new object on each interpolation.
def foo(): ...
d = {}
"{x} {x}".format(x=foo())
"{x} {x}".format(x=d["k"])
"{x} {x}".format(x=(y := 1))
"{x.append} {x.append}".format(x=list())
When the argument is interpolated once, the side effect runs once either way, so the fix is safe.
def foo(): ...
"{x}".format(x=foo()) # snapshot: f-string
error[UP032]: Use f-string instead of `format` call
--> src/mdtest_snippet.py:4:1
|
4 | "{x}".format(x=foo()) # snapshot: f-string
| ^^^^^^^^^^^^^^^^^^^^^
|
help: Convert to f-string
1 | def foo(): ...
2 |
3 |
- "{x}".format(x=foo()) # snapshot: f-string
4 + f"{foo()}" # snapshot: f-string