f-strings vs str.format()
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- Optimizations to CPython might make
.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.
f-string representation different than str()
From "Formatted string literals" in the Python reference:
f-strings are invoke the "format
protocol", same as the format
built-in function. It means that the __format__
magic method is called instead of __str__
.
class Foo:
def __repr__(self):
return "Foo()"
def __str__(self):
return "A wild Foo"
def __format__(self, format_spec):
if not format_spec:
return "A formatted Foo"
return f"A formatted Foo, but also {format_spec}!"
>>> foo = Foo()
>>> repr(foo)
'Foo()'
>>> str(foo)
'A wild Foo'
>>> format(foo)
'A formatted Foo'
>>> f"{foo}"
'A formatted Foo'
>>> format(foo, "Bar")
'A formatted Foo, but also Bar!'
>>> f"{foo:Bar}"
'A formatted Foo, but also Bar!'
If you don't want __format__
to be called, you can specify !s
(for str
), !r
(for repr
) or !a
(for ascii
) after the expression:
>>> foo = Foo()
>>> f"{foo}"
'A formatted Foo'
>>> f"{foo!s}"
'A wild Foo'
>>> f"{foo!r}"
'Foo()'
This is occasionally useful with strings:
>>> key = 'something\n nasty!'
>>> error_message = f"Key not found: {key!r}"
>>> error_message
"Key not found: 'something\\n nasty!'"
What's the difference between f{x} and {}.format(x) in python?
Python f-strings were added in 3.6. Therefore you should consider using format() if you need compatibility with earlier versions. Otherwise, use f-strings.
On macOS 12.1 running 3 GHz 10-Core Intel Xeon W and Python 3.10.2, f-strings are significantly faster (~60%)
String formatting: % vs. .format vs. f-string literal
To answer your first question... .format
just seems more sophisticated in many ways. An annoying thing about %
is also how it can either take a variable or a tuple. You'd think the following would always work:
"Hello %s" % name
yet, if name
happens to be (1, 2, 3)
, it will throw a TypeError
. To guarantee that it always prints, you'd need to do
"Hello %s" % (name,) # supply the single argument as a single-item tuple
which is just ugly. .format
doesn't have those issues. Also in the second example you gave, the .format
example is much cleaner looking.
Only use it for backwards compatibility with Python 2.5.
To answer your second question, string formatting happens at the same time as any other operation - when the string formatting expression is evaluated. And Python, not being a lazy language, evaluates expressions before calling functions, so the expression log.debug("some debug info: %s" % some_info)
will first evaluate the string to, e.g. "some debug info: roflcopters are active"
, then that string will be passed to log.debug()
.
Is there a difference between f and F in Python string formatting?
As explained in the PEP 498, chapter Specification, both are accepted, and should not differ.
In source code, f-strings are string literals that are prefixed by the letter 'f' or 'F'. Everywhere this PEP uses 'f', 'F' may also be used.
Why are f-strings faster than str() to parse values?
The simple answer is because f-strings are part of the language's grammar and syntax. The str()
call on the other hand requires a symbol table lookup, followed by a function call.
Here's a similar example which interpolates an integer variable, contrast this with the constant value interpolation.
x = 1
%timeit f'{1}'
%timeit f'{x}'
%timeit str(1)
%timeit str(x)
113 ns ± 2.25 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
166 ns ± 4.71 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
342 ns ± 23.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
375 ns ± 11.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
The difference in the behaviour is obvious when you look at the disassembled byte code with dis
.
import dis
dis.dis("f'{x}'")
1 0 LOAD_NAME 0 (x)
2 FORMAT_VALUE 0
4 RETURN_VALUE
dis.dis("str(x)")
1 0 LOAD_NAME 0 (str)
2 LOAD_NAME 1 (x)
4 CALL_FUNCTION 1
6 RETURN_VALUE
The heavy lifting is all in the CALL_FUNCTION
instruction, an overhead which f-strings certainly don't have -- at least in this case, as nothing needs to be eval
'd.
Related Topics
Pyaudio Working, But Spits Out Error Messages Each Time
How to Get Indices of a Sorted Array in Python
Function for Factorial in Python
How to Execute Python Code from Within Visual Studio Code
Cmd Opens Windows Store When I Type 'Python'
How to Interpret Conda Package Conflicts
How to Convert This List of Dictionaries to a CSV File
Typeerror: a Bytes-Like Object Is Required, Not 'Str' in Python and CSV
Python Cannot Handle Numbers String Starting with 0. Why
Create a "With" Block on Several Context Managers
Python Unexpected Eof While Parsing
Django Passing Custom Form Parameters to Formset
Replacing Few Values in a Pandas Dataframe Column with Another Value
Differencebetween Contiguous and Non-Contiguous Arrays
Given a Url to a Text File, What Is the Simplest Way to Read the Contents of the Text File