Why call str
on the elements? Why not repr
, or ascii
, or some other converter?
We need to distinguish between functions which are part of a low-level API, and those expected to work as part of a higher level API.
print
has a high-level API. It should be polymorphic, and work with any type. I should be able to print any object at all, and get something sensible, without caring too much about it. It’s okay for print
to guess what converter we want.
I’m unlikely to capture the output of print
and use it in other computations, so “something sensible” doesn’t need to be too precise.
str.join
is part of a low-level string API. It is right and proper that it only works on strings, not arbitrary objects. Being low-level, it shouldn’t guess what to do with non-string values:
- is it an error? if so, raise
- or does the programmer intend there to be a non-string in the input?
- if so, how does the programmer want to convert the value into a string?
A low-level API should not guess what is wanted. In this case, explicit is better than implicit:
sep.join(map(ascii, values))
If you want a high-level joiner that works on anything, like print, its a one-liner:
def join(values, *, sep=''):
return sep.join([str(obj) for obj in values])
But it hardly seems worth it, for such a simple operation. YMMV.