True, though you end up with things like:
' '.join(thelist)
Instead of thelist.join(' ')
Because of the somewhat aggressive mantra to be consistent.For example, scala has Iterable#mkstring (https://docs.scala-lang.org/overviews/collections-2.13/trait...)
JS:
Array.prototype.join.call(["one", "two", "three"], "|")
Python: str.join("|", ["one", "two", "three"])Ruby does it by having a mixin (Enumerable) that anything meeting a basic contract (roughly equivalent to the Python iterable protocol) can include to get an enormous block of functionality; Python doesn’t have (or at least idiomatically use as freely; ISTR that there is a way to do it) mixins like Ruby does.
Javascript, on the other hand, kinda does it worst, at least of the languages I regularly use... .join() is a instance method on Arrays and TypesArrays. But they forgot to add any kind of join for Sets, for example.
(["a", "b", "c"]).join("")
"abc" # alright
(new Set(["a", "b", "c"])).join("")
Uncaught TypeError: (intermediate value).join is not a function
([...new Set(["a", "b", "c"])]).join("")
"abc" # grmpf, have to materialize it into an array first.
That illustrates the drawback: if you make it a method on the concrete sequence types you got, you better not forget some and make sure the different APIs are consistent, too. If Javascript had a String.join(sep, <anything implementing the iterator protocol>) this wouldn't have been an issue.python isn't alone either, by the way. C# has the static string.Join(...) that accepts "enumerables" (IEnumerable<T>), but no array.Join() or list.Join() or dictionary.Join(). Combined with Linq, especially .Select, that becomes quite handy. It has been plenty of times I did print-debugging by adding a one liner along the lines of
Console.WriteLine(string.Join("\n", dictionary.Select((key, value) => $"{key} = {value.SomeProperty}")));
I find the C# way of having a string.Join(sep, ...) instead of python's "some string".join(...) nicer to read because it's more obvious.`str.join(sep, ...)` works in Python as well, because `a.f(...)` and `type(a).f(a, ...)` are (almost) equivalent.
str.join() and bytes.join() can support all iterable type arguments.
Better than trying to implement a join (or two) on all iterables.