问题
Let's say I have two variables:
>>> a = "hello"
>>> b = "world"
I can concatenate them in two ways; using +
:
>>> a + b
"helloworld"
Or using an f-string:
>>> f"{a}{b}"
"helloworld"
Which way is better or a better practice? Someone told me the f-string is better practice in terms of performance and robustness, and I'd like to know why in detail.
回答1:
There are two aspects to this: performance and convenience.
Using timeit in Python 3.8.0, I get that concatenation using an f-string is consistently slower than +
, but the percentage difference is small for longer strings:
>>> from timeit import timeit
>>> timeit('a + b', setup='a, b = "hello", "world"')
0.059246900000289315
>>> timeit('f"{a}{b}"', setup='a, b = "hello", "world"')
0.06997206999949412
>>> timeit('a + b', setup='a, b = "hello"*100, "world"*100')
0.10218418099975679
>>> timeit('f"{a}{b}"', setup='a, b = "hello"*100, "world"*100')
0.1108272269993904
>>> timeit('a + b', setup='a, b = "hello"*10000, "world"*10000')
2.6094200410007033
>>> timeit('f"{a}{b}"', setup='a, b = "hello"*10000, "world"*10000')
2.7300010479993944
However, the f-string may be a bit more convenient when your inputs aren't already strings:
>>> a, b = [1, 2, 3], True
>>> str(a) + str(b)
'[1, 2, 3]True'
>>> f'{a}{b}'
'[1, 2, 3]True'
回答2:
Performance wise, I would have expected the format string literal to be significantly faster than string concatenation however I was shocked to find this was not the case.
I used the timeit
module to test how long it took format string literals vs. string concatenation. I tested strings of length 10 to 1 million characters.
from timeit import timeit
import matplotlib.pyplot as plt
n = 1000000000
setup = """\
a = 'a'*{str_len}
b = 'b'*{str_len}
"""
fstr_stmt = """\
f'{a}{b}'
"""
concat_stmt = """\
a+b
"""
str_lens = [10, 100, 1000, 10000, 100000, 1000000]
fstr_t = []
concat_t = []
for str_len in str_lens:
n_iters = n//str_len
fstr_t.append(timeit(setup=setup.format(str_len=str_len), stmt=fstr_stmt, number=n_iters)/n_iters)
concat_t.append(timeit(setup=setup.format(str_len=str_len), stmt=concat_stmt, number=n_iters)/n_iters)
ratio = fstr_t[-1]/concat_t[-1]
print(f"For two strings of length {str_len:7d}, concatenation is {ratio:.5f} times faster than f-strings")
plt.plot(str_lens, fstr_t, "r*-")
plt.plot(str_lens, concat_t, "c*-")
plt.xscale("log")
plt.yscale("log")
plt.xlabel("String length (log scale)")
plt.ylabel("Seconds per iteration (log scale)")
plt.grid()
plt.show()
Console Output:
For two strings of length 10, concatenation is 1.06938 times faster than f-strings
For two strings of length 100, concatenation is 1.14887 times faster than f-strings
For two strings of length 1000, concatenation is 1.13994 times faster than f-strings
For two strings of length 10000, concatenation is 1.26934 times faster than f-strings
For two strings of length 100000, concatenation is 1.21585 times faster than f-strings
For two strings of length 1000000, concatenation is 1.01816 times faster than f-strings
And the plot:
Summary: Using the string concatenation operator is slightly faster than using format string literals. Unless you are performing many hundreds of thousands of string concatenations and need them done very quickly, the implementation chosen is unlikely to make a difference.
From a readability standpoint, f-string literals are more aesthetically pleasing and easier to read than string concatenation. Also, as the answer from Daniel points out, f-strings are able to handle inputs of different types while using +
requires both objects to be strings (or the overloading of the __add__
, and __radd__
methods).
Edit: As chepner points out in their comment, using f-strings is more efficient when more than two strings are involved. For example, adding another variable, c
, to the setup and timeit
statements yields the following console output:
For three strings of length 10, concatenation is 0.77931 times faster than f-strings
For three strings of length 100, concatenation is 0.67699 times faster than f-strings
For three strings of length 1000, concatenation is 0.60220 times faster than f-strings
For three strings of length 10000, concatenation is 1.27484 times faster than f-strings
For three strings of length 100000, concatenation is 0.98911 times faster than f-strings
For three strings of length 1000000, concatenation is 0.60201 times faster than f-strings
回答3:
Well method 2 is a clearer way to express that you want the strings to be concatenated together. That is why I would suggest using that method in the case you've provided.
The problem with method one is when you start using different Types.
# integers
a = 1
b = 2
a + b # 3
f'{a}{b}' # 12
# lists
a = [2, 3]
b = [5, 6]
a + b # [2, 3, 5, 6]
f'{a}{b}' # [2, 3][5, 6]
# dicts
a = {'a': 3}
b = {'a': 5}
a + b # TypeError
f'{a}{b}' # {'a': 3}{'b': 5}
When the values are anything but strings you will get a different results. I can't speak to performance, but depending on how many times the line is executed it could have almost no difference.
来源:https://stackoverflow.com/questions/59180574/string-concatenation-with-vs-f-string