There is a great answer from SilentGhost, but just a few words about the presented reduce "alternative":
Unless you've got a very very very good reason to concatenate strings using + or operator.add (the most frequent one, that you've got few, fixed number of strings), you should use always join.
Just because each + generates a new string which is the concatenation of two strings, unlike join that only generates one final string. So, imagine you've got three strings:
A + B + C
-->
D = A + B
final = D + C
Ok, it doesn't seems not much, but you've got to reserve memory for D. Also, due Python's use of strings, generating a new, intermediate, string, it's somehow expensive...
Now, with five strings,
A + B + C + D + E
-->
F = A + B
G = F + C
H = G + D
final = H + E
Assuming the best scenario (if we do (A+B) + (C+D) + E, we'll end having three intermediate strings at the same time on memory), and that's generating three intermediate strings... You've got to generate a new Python object, reserve memory space, and release the memory a few times... Also there is the overhead of calling a Python function (that is not small).
Now think of it with 200 strings. We'll end up with a ridiculous big number of intermediate strings, each of which is consuming combining quite a lot of time on being a complete list over Python , and calling a lot of operator.add functions, each with its overhead...
Even if you use reduce functions, it won't help. It's a problem that has to be managed with a different approach: join, which only generates one complete Python string, the final one and calls one Python function.
(Of course, join, or other similar, specialized function for arrays.)