Python 中连接两个字符串的方法有两个: + 和 join()
当我开始使用 Python 的时候,通常会使用 + 这个运算符来连接字符串,这个方法简单又直接。
后来在看其他的人代码,他们却喜欢使用 .join() 这个方法连接字符串,下面我来说一说为什么大家更倾向使用 .join(),而不是 +这个运算符。
开始
作为初学者,使用 + 运算符连接字符串,代码很简单:
str1 = "I love "
str2 = "Python."
print(str1 + str2)
# 输出
# I love Python
当深入学习后,会发现其他人的代码更倾向于使用 join() 方法,像这样:
str1 = "I love "
str2 = "Python."
print(' '.join([str1, str2]))
# 输出
# I love Python
说实在的,当我看见上面的代码,我觉得它很不直观,而且还不好看。
连接多个字符串
不过,这一次我们需要连接列表中的多个串。
strs = ['Life', 'is', 'short,', 'I', 'use', 'Python']
最初,我是这样写的:
strs = ['Life', 'is', 'short,', 'I', 'use', 'Python']
def join_strs(strs):
result = ''
for s in strs:
result += ' ' + s
return result[1:] # 删除前面的空格
join_strs(strs)
# 输出
# Life is short, I use Python
在这个例子里,我是用 for 循环一个一个的连接字符串,最后我还要去除第一个字符前面的空格,因为循环里每次连接的时候,都在前面加了一个空格。当然,也可以通过在 for 循环里面加一个判断,当 index = 0 的时候不加这个空格,不管怎样,都要用 for 循环去做这些事情。
当我知道 .join() 这个方法的时候:
def jion_strs_better(strs):
' '.join(strs)
jion_strs_better(strs)
# 同样输出
# Life is short, I use Python
是不很简单,一行代码就解决了这个问题,而且不用考虑空格的问题。
不过,这个优点并不是放弃使用 + 运算符,转向 join() 方法的原因。
join() 方法背后的逻辑
接下来我们比较一下这两个方法的性能,可以使用 Jupyter Notebook 的魔法糖方法 %timeit 对这两个方法进行评估。
上面显示的性能结果是通过十万次的操作得出来的,所以结果显而易见:使用 join() 方法连接列表中的字符串,比使用 + 运算符要快4倍。
为什么会有这么大差距呢?
下图就是使用 + 运算符通过 for 循环连接字符串的过程:
- 通过 for 循环,找到每个字符串。
- Python 执行表达式 result += ' ' + s 并且为 空格申请内存地址(get memory for a white space)
- 然后执行程序意识到空格也需要与字符串连接,因此它也将为字符串申请内存地址,第一个循环为 Life (get memory for "life")
- 对于每次循环,执行器都要申请两次内存地址,一次为空格,一次为字符串
- 总共需要12次的内存地址分配
我们再来看一下 join() 方法:
- 执行器首先会计算列表里有多少个字符串,例子中是6个
- 这意味这连接列表里面的字符串需要重复 6-1=5次
- 所以执行器知道此次操作需要分配 11 个内存地址,这些会被预先应用和分配
- 然后按顺序执行并返回结果
所以两个方法的主要差别就是在内存地址分配次数上,这是这两个方法性能差别的主要原因。
想象一下,使用 join()方法连接 6 个字符串已经比 + 运算符快了4倍。如果要连接更多的字符串呢,这种差别也会是更大。
总结
在这篇文章中,我们比较了 Python 连接两个字符串 + 运算符和 join() 的区别,从性能方面比较,join() 是首选。