I'm using the .format()
a lot in my Python 3.5 projects, but I'm afraid that it will be deprecated during the next Python versions because of f-strings, the new kind of string literal.
>>> name = "Test"
>>> f"My app name is {name}."
'My app name is Test.'
Does the formatted string feature come to fully replace the old .format()
? And from now on, would it be better to use the new style in all cases?
I understand that it's based on the idea that "Simple is better than complex." However, what about performance issues; is there any difference between them? Or is it just a simple look of the same feature?
There is no difference as you see. Both are string formatting options, with f-strings being newly introduced.
There's no difference in terms of the output it produces. The result variable will have the same contents in each case. But String. format() is there so that you can do more powerful formatting, including specifying number of decimal places for floating point numbers, and the like.
There is no difference at all. See the definition of Formatted string literals in the Python documentation. A formatted string literal or f-string is a string literal that is prefixed with 'f' or 'F'. No further mention is made of the specific character used to introduce the literal.
From a readability standpoint, f-string literals are more aesthetically pleasing and easier to read than string concatenation.
I'm afraid that it will be deprecated during the next Python versions
Don't be, str.format
does not appear (nor has a reason) to be leaving any time soon, the PEP that introduced f
prefixed-strings even states in its Abstract:
This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms.
Formatted strings were introduced to address some of the shortcomings other methods for formatting strings had; not to throw the old methods away and force god-knows how many projects to use f-string's if they want their code to work for Python 3.6+.
As for the performance of these, it seems my initial suspicion that they might be slower is wrong, f-strings seem to easily outperform their .format
counterparts:
➜ cpython git:(master) ./python -m timeit -s "a = 'test'" "f'formatting a string {a}'"
500000 loops, best of 5: 628 nsec per loop
➜ cpython git:(master) ./python -m timeit "'formatting a string {a}'.format(a='test')"
100000 loops, best of 5: 2.03 usec per loop
These were done against the master branch of the CPython repository as of this writing; they are definitely subject to change:
f-strings
, as a new feature, might have possible optimizations .format
faster (e.g Speedup method calls 1.2x) But really, don't worry about speed so much, worry about what is more readable to you and to others.
In many cases, that's going to be f-strings
, but there's some cases where format
is better.
To build on Jim's answer and address your performance concern, I used python's dis
module to compare the bytecode instructions for two syntactically different, but functionally equivalent functions.
import dis
def f1():
a = "test"
return f"{a}"
def f2():
return "{a}".format(a='test')
print(dis.dis(f1))
print(dis.dis(f2))
The result of which is:
11 0 LOAD_CONST 1 ('test') 2 STORE_FAST 0 (a) 12 4 LOAD_FAST 0 (a) 6 FORMAT_VALUE 0 8 RETURN_VALUE None 15 0 LOAD_CONST 1 ('{a}') 2 LOAD_ATTR 0 (format) 4 LOAD_CONST 2 ('test') 6 LOAD_CONST 3 (('a',)) 8 CALL_FUNCTION_KW 1 10 RETURN_VALUE None
One can see that the f-string handles the formatting without attribute or function calls, which can impose type checking and memory overhead. According to timeit
this results in a roughly 3x performance gain (for my specific functions)
>>> timeit.timeit('f1()', 'from __main__ import f1', number=100000) 0.012325852433775708 >>> timeit.timeit('f2()', 'from __main__ import f2', number=100000) 0.036395029920726074
One thing not mentioned, which makes deprecation of the old techniques impossible, is that interpolation is for string literals only. Meaning, the string is rendered once at runtime, and the template is not available to be used again with updated variables. As you would for example:
>>> str_template = '{i} squared: {n}'
>>> for i in range(2, 5):
... print(str_template.format(i=i, n=i**2))
...
2 squared: 4
3 squared: 9
4 squared: 16
Another case is i18n, where string.Template
is used. Many use cases would be impossible without the older techniques. Enjoy string interpolation, but it is not available to every use case, i.e. places where you need a reusable template.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With