Definitely, one of the most boring and repetitive patterns I find myself typing is ", ".join(str(i) for i in mything). If str.join would call __str__ in each element in the iterator it is given, this kind of code could be simply ", ".join(mything).
I don’t see this change breaking anything, and I see a lot of real-world code getting rid of a pain to get a pretty output.
Also, I can’t see this having any compatibility issues, since, up to know everyone has to painstakingly iterate over their sequence and manually call str() on it.
This has been suggested in the past and rejected because it will hide bugs I recall.
You cannot know how to convert all the objects into strings with the correct formatting in the general case. Objects that do not have a __str__, for example, fall back to __repr__ that is often not what is expected.
This seems a weak counter-argument.
It would still work as expected in 99% of the cases - for both novice and expert Python programmers (experts will know and be expecting __repr__ to be called, actually).
The effect, anyway, is not different from what one gets when printing an arbitrary object,
and we don’t see people being hurt by that behavior.
And still, it just make a shorter, garbage free, version of the same expression possible -
one is still free to implement a generator expression if the string conversion is to be
more complicated than calling str() on the object.
Maybe, an optional flag “strict” defaulting to False, that would cause it to type-error
as the current implementation does, just in case someone’s code depends
on it failing like that.
Do you have links to where the discussion has ocured before?
I can dig there and see if there are any actual arguments against this
And you would save an incredible five characters! What a difference that makes! Right?
Or you can write a helper function once, and save about 20 characters: join(mything).
What you are proposing is a form of weak typing. Python is a strongly-typed language, with very little weak typing, and (almost?) all of that is in automatic coercion of different numeric types.
It is never automatic coercion of strings to ints, or ints to strings (for example). Weak typing has the benefit of saving keystrokes. Strong typing has the benefit of preventing bugs. Some languages are even stronger than Python, and don’t allow automatic numeric coercion.
In the last few weeks, this same issue has come up at least twice, and I responded both times:
I agree this is a great idea. Besides making the code nicer, we can also provide a speedup over user code to coerce the input to strings. FWIW, I had run a Twitter poll on the subject. 3,370 voted and 78.1% want to have this change approved.
Regarding worries about explicit vs implicit, experience with print() has shown this to be non-issue. One respondent did a nice job of summarizing why:
Given that I have already chosen that the final output should be a string, the explicitness criterion is already fulfilled. Thus, there is no reason to jump all the arguments through a hoop.
I don’t see where you’re getting this from. Are you saying that Python’s philosophy has changed from how it was in some distant past when it was a toy language, and now that it’s a real language, … no, I can’t figure out what you mean by the “consenting adults” part.
There’s a major difference between print() and str.join(). The latter is a low level operation on arbitrary sequences/iterables, which are expected to provide string elements (not providing these is an error, which code may very well rely on to prevent data corruption). The former explicitly asks to stringify the arguments, so that they can be printed to stdout.
The argument would work, if we’d add a new builtin or some helper concat() or perhaps a new constructor str.concat() which also explicitly asks for stringification of the arguments, in the same way print() works.
It would also make a lot of sense, to have it use almost the same signature as print() does, i.e.
concat(*objects, sep=' ', end='')
returning the concatenated string sep.join([str(x) for x in objects]) + end, only faster
As a side effect, the function would also resolve the weirdness many people find in having to write ', '.join(list) to build a string from several other strings.
I already see people writing ", ".join(a, b) expecting to get a and b joined with , often enough that linters will start requiring the optional argument to the join() method to be specified by name. Thus we are going from the fairly self explanatory and concise
“Hey, we should make this big change because it’d be convenient in a few places!”
“That’s a bad idea, and it would break existing code.”
“Then let’s make a boolean flag for it!”
Adding a flag does mean that the change won’t break existing code, but it’s also a VERY ugly way to do things. As soon as you add this flag to one method, you’re going to get people asking for it on every other method as well. It’s not even clear that this functionality is worth having, much less that it’s worth polluting the API with a kwonly parameter all over the place.
Is it really THAT hard to write your own strjoin function that maps str over the iterable and then joins the results?