No issues with moving to str.format
, f-strings have some pros and cons. For formatting a values already assigned to variables, it reads nicely.
As with the example f"ssh {username}@{hostname}"
The down-sides for Blender’s Python code are…
-
This doesn’t work so well when the contents of f-strings contains function calls, operators … etc, take this example.
return """<input type="checkbox" title="{:s}" {:s} {:s}>""".format( title, "checked" if value else "", ("onclick=\"{:s}\"".format(script)) if script else "", )
Of course we can refactor code to read better, assign variables before using them in some cases, but this makes the project a bigger task.
The case above is a little extreme (especially that it includes a format within a format), even in simpler cases, f-strings don’t necessarily read very well, we often use unpacking from vector types, which you don’t get with f-strings.
I find this:
file.write("{:4f}, {:4f}, {:4f}".format(*(matrix @ vertex.co)))
More readable than this:
vertex_co = matrix @ vertex.co file.write(f"{vertex_co[0]:4f}, {vertex_co[1]:4f}, {vertex_co[2]:4f}")
This function in
release/scripts/modules/rna_prop_ui.py
, doesn’t convert easily.def rna_idprop_quote_path(prop): return "[\"%s\"]" % prop.replace("\"", "\\\"")
… I ran into the error:
SyntaxError: f-string expression part cannot include a backslash
.Again, assigning variables could work here, it’s just an example where f-strings can’t be used as drop-in replacements for existing code.
Less extreme cases are always disputable, having already looked into moving to f-strings, there are enough cases in Blender’s code that don’t convert cleanly, making them less useful as a general replacement for existing formatting.
-
Many editors still don’t properly syntax highlight code in f-strings (including Blender’s).
-
Tooling around Python don’t fully support f-strings. Autopep8 for e.g. wont auto-format code inside f-strings.
-
For UI labels f-strings will extract code in the translation string, so translation strings will be more verbose & likely to change more often, although I’d want to double check with @mont29 about this.
-
Moving between f-strings and
str.format
adds some overhead, we may start out using with formatting that works well as an f-string, later on more complex logic could be added into the existing f-string (which I’d rather avoid), or the f-string needs to be converted into astr.format
, which takes time and has potential for human error. -
If there are cases where we do/don’t use f-strings, we need to document & communicate this, explain in patch review, request edits that add/remove it, explain that UI translations are an exception, discuss when it is/isn’t readable … which takes time and is subjective.
You can use str.format
with named arguments, if argument order makes the formatting less readable.
"{foo:s} {bar:d} {baz:f}".format(
foo=some(b, 'c'),
bar=non(d, e),
baz=trivial('code', ":)"),
)
This avoids filling the local name-space with single use variables that can be used by accident or show up un-helpfully in auto-complete.
So moving to str.format
seems fine.
As for f-strings, I’d rather only use f-strings in cases where they use basic variables & attributes, where it’s unlikely we introduce more complex logic. Although having two ways of doing something thats subjective makes me less inclined to want to use them.