String concatenation with + vs. f-string

99封情书 提交于 2020-04-30 06:24:47

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!