f-strings are very handy and readable. But they are evaluated where they are coded.
robot = "positronic"
statement = f"I want a {robot} brain"
If you want a reusable template, you have to use format
or the %
syntax with a “normal” string:
robot = "positronic"
tpl = "I want a {robot} brain"
statement = tpl.format(robot=robot)
If you have a lot of interpolations to do, this will turn to be quite tedious very quickly. This is one of the reasons f-strings became so popular.
I propose to add yet another method to str, to interpolate the string like it is an f-string:
robot = "positronic"
tpl = "I want a {robot} brain"
statement = tpl.interpolate()
In this way you can have a reusable template easy to use as an f-string.
If PEP 750 will be implemented, obviously this proposal will became superseded.
Side note: interpolate
seems to me too long, but I can’t think a better name now.
pf_moore
(Paul Moore)
January 24, 2025, 8:51pm
2
You can use tpl.format(**locals())
.
4 Likes
This is a good way to do this “right now” I didn’t think about and I’ll definitively use it. Notice anyway this does not work as f-strings, since they can accept also globals and expressions.
Rosuav
(Chris Angelico)
January 24, 2025, 10:04pm
4
Lucas Malor:
I propose to add yet another method to str, to interpolate the string like it is an f-string:
robot = "positronic"
tpl = "I want a {robot} brain"
statement = tpl.interpolate()
In this way you can have a reusable template easy to use as an f-string.
If it were plausible to do that, we wouldn’t have needed f-strings in the first place, and the method would have been sufficient.
MegaIng
(Cornelius Krupp)
January 24, 2025, 10:12pm
5
You can do eval('f' + repr(tpl))
. Note that the usage of eval
correctly indicates that this a dangerous operation that opens you up to security issues if you do it with untrusted data.
4 Likes
Stefan2
(Stefan)
January 25, 2025, 1:45pm
6
Or tpl.format_map(locals())
.
And another:
robot = "positronic"
tpl = lambda: f"I want a {robot} brain"
statement = tpl()
4 Likes
I think this is the best solution.
effigies
(Chris Markiewicz)
January 26, 2025, 9:28pm
8
FWIW, when I need to do something like this, I either do:
fmt = "I want a {} brain".format
fmt("positronic")
Or:
fmt = "I want a {robot} brain".format
fmt(robot="positronic")
The lambda
trick will work if I’m doing something like:
timestamp = lambda: f"Elapsed time {time.time() - tic}"
tic = time.time()
# Do something
timestamp()
# Do something else
timestamp()
But I think I’m not polling the value of a changing variable or expression as often as I want to format a bunch of one-off values.
1 Like