Why is join() a string method instead of a list or tuple method?
Strings became much more like other standard types starting in Python 1.6, when methods were added which give the same functionality that has always been available using the functions of the string module. Most of these new methods have been widely accepted, but the one which appears to make some programmers feel uncomfortable is:
", ".join(['1', '2', '4', '8', '16'])
which gives the result:
"1, 2, 4, 8, 16"
There are two usual arguments against this usage.
The first runs along the lines of: “It looks really ugly using a method of a string literal (string constant)”, to which the answer is that it might, but a string literal is just a fixed value. If the methods are to be allowed on names bound to strings there is no logical reason to make them unavailable on literals.
The second objection is typically cast as: “I am really telling a sequence to join its members together with a string constant”. Sadly, you aren’t. For some reason there seems to be much less difficulty with having split as a string method, since in that case it is easy to see that
"1, 2, 4, 8, 16".split(", ")
is an instruction to a string literal to return the substrings delimited by the given separator (or, by default, arbitrary runs of white space). In this case a Unicode string returns a list of Unicode strings, an ASCII string returns a list of ASCII strings, and everyone is happy.
join is a string method because in using it you are telling the separator string to iterate over an arbitrary sequence, forming string representations of each of the elements, and inserting itself between the elements’ representations. This method can be used with any argument that implements the iterator or sequence protocols, including any new classes you might define yourself.
Because this is a string method it can work for Unicode strings as well as plain ASCII strings. If join were a method of the sequence types then the sequence types would have to decide which type of string to return depending on the type of the separator.
string.join(['1', '2', '4', '8', '16'], ", ")
This still dispatches on the separator under the covers, but you can pretend that it doesn’t.