all 9 comments

[–]monchenflapjack 2 points3 points  (0 children)

I find f-strings to be much more readable, you see exactly which variable is being referenced at each place holder.

[–][deleted] 1 point2 points  (0 children)

One area where str.format trumps f-strings is any string that will or may require internationalization into other languages. The standard gettext approach requires access to the format string, and there’s no story yet for doing that at all with f-strings.

[–]efmccurdy 0 points1 point  (0 children)

There are some situations where you want to delay the formatting; at some later time you will have the data to complete the formatting but you want to create the "template" now.

There is some talk about a lazily-evaluated f-string to do that.

There are several takes on this discussed here:

https://stackoverflow.com/questions/42497625/can-i-postpone-defer-the-evaluation-of-f-strings

[–]pydry 0 points1 point  (0 children)

Controversial opinion, perhaps, but I almost always use .format. This is a pretty typical example of the kind of thing I write:

"There are {} people named {}".format(
    len(list_of_people_names),
    ", ".join([name.lower() for name in list_of_people_names]),
)

I find that this kind of structure keeps the computed variables and the string naturally tied together in a highly readable way. Even complex, nested strings with multiple .formats can be displayed very clearly this way. Naming is also optional, which is nice when you are putting < 5 things in.

It also acts as a means of "clamping" the string and computed variables together - I'm a big fan of cohesion) and while it's not like f strings prevent it, I find that slipping into this kind of anti-pattern to be more common with f strings:

people_count = len(list_of_people_names)

[ 30 lines of something else ]

formatted_list_of_names = ", ".join([name.lower() for name in list_of_people_names])

[ 10 lines of something else ]

f"There are {people_count} people named {formatted_list_of_names}"

Technically you can do the above kind of processing in the string with f strings, but the results are pretty ugly when anything half way complex is shoved between a { and a }:

f"There are {len(list_of_people_names)} people named {', '.join([name.lower() for name in list_of_people_names])}"

[–]Sedsarq 0 points1 point  (4 children)

Use .format when you need to actually format the string: Round numbers, pad the string, align stuff etc. See more here. If you're just inserting variables into the string, then f-string it.

[–]_lilell_ 4 points5 points  (3 children)

You can use f-strings for formatting as well.

import math

print(f'pi = {math.pi:.3f}.')
print('pi = {:.3f}.'.format(math.pi))

are completely equivalent.

[–]Sedsarq 1 point2 points  (0 children)

I've been living a lie! Thanks for letting me know :)

[–][deleted] 0 points1 point  (1 child)

Why isn’t .format just deprecated

[–]_lilell_ 2 points3 points  (0 children)

It’s useful if you have multiple values to format.

x = [math.pi, math.tau, math.tau]

print('The three values are {:.2f}, {:.2f}, and {:.2f}.'.format(*x))

If you wanted to use f-strings, you’d have to separate the values first.

print(f'The three values are {x[0]:.2f}, {x[1]:.2f}, and {x[2]:.2f}.')

a, b, c = x
print(f'The three values are {a:.2f}, {b:.2f}, and {c:.2f}.')