0

Here's a transcript of what I want to do. It currently fails in both Python 2.7 and 3.4:

>>> a = [3,4,5]
>>> ','.join(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: sequence item 0: expected string, int found

This works, but is clumsy and potentially inefficient:

>>> ','.join(map(str, a))
'3,4,5'

My question is, does anything prevent us from enhancing Python to support str.join() on non-string iterables (so long as they are convertible to strings, e.g. by str())? I looked for a PEP about this but didn't find any.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • 3
    I don't see how using `map` or a list comprehension is clumsy. I'd imagine it'd be even more clumsy having a function automatically coercing objects to strings. After all, [is explicit not better than implicit](http://legacy.python.org/dev/peps/pep-0020/)? – Ffisegydd Aug 14 '14 at 14:22
  • 1
    Python prefers **explicit** actions over implicit. See the [Zen of Python](http://legacy.python.org/dev/peps/pep-0020/). – Martijn Pieters Aug 14 '14 at 14:24
  • @Ffisegydd: Perhaps clumsy is the wrong word. How about clunky? Verbose? Non-intuitive? Pointless? I mean, yes map works, but I've seen everyone from casual to frequent Python users write a join without using str() and have their code fail the first time through. It seems unnecessary. – John Zwinck Aug 14 '14 at 14:24
  • @MartijnPieters: Sure, but we have print which stringifies things automatically, because it's pointless not to (why would you want it to fail when it only has one possible valid meaning)? Why should print do it but str.join shouldn't? Aren't they rather similar? – John Zwinck Aug 14 '14 at 14:26
  • @John no... `str.join` is optimised for exactly that - joining strings... - it's the same reason that `sum` although it applies `+` to each item, refuses to operate on strings... – Jon Clements Aug 14 '14 at 14:26
  • For the purpose of this discussion, who is "us"? – Karl Knechtel Aug 14 '14 at 14:27
  • @JohnZwinck print doesn't stringify everything automatically. Try `print "hi" + 3` and watch it fail. – TheSoundDefense Aug 14 '14 at 14:28
  • The facetious solution, if you want to be able to construct a string and then use a single method call on it: `('{},' * len(a))[:-1].format(*a)` :) – Karl Knechtel Aug 14 '14 at 14:30
  • 1
    _"does anything prevent us from enhancing Python?"_ Not at all. Go ahead and modify your local build of Python however you want :-) – Kevin Aug 14 '14 at 14:31
  • @JohnZwinck: beyond the command line, `print()` is a debug tool though; the `logging` module also turns everything to strings. So no, `str.join()` and `print()` are not similar. – Martijn Pieters Aug 14 '14 at 14:31
  • @Martijn I don't know... `print >> fout, var1, var2` or `print(var, var2, sep='\t', file=fout)` are useful in production code (so I'd disagree it's purely a debug tool) – Jon Clements Aug 14 '14 at 14:32
  • @Kevin: I am more interested in knowing if there is a good reason why adding this functionality would break anything. Or if it was proposed previously (and perhaps rejected). – John Zwinck Aug 14 '14 at 14:33
  • @JonClements: right, but that's extra utility for a statement / function beyond its original usecase. – Martijn Pieters Aug 14 '14 at 14:33
  • 1
    Would it be appropriate to [continue this discussion in the Python chatroom](http://chat.stackoverflow.com/rooms/6/python)? Rather than a comment thread :) – Ffisegydd Aug 14 '14 at 14:34
  • 2
    @JohnZwinck: https://mail.python.org/pipermail/python-ideas/2010-October/008358.html; by being explicit about it you get to detect bugs where you did not mean to pass in objects that were not strings. That's from the Python ideas list, and that's the language author Guido van Rossum rejecting the idea. – Martijn Pieters Aug 14 '14 at 14:35
  • @JonClements: clearly "sum" on strings may not be intuitive, and summing "3" and "5" to "35" could be outright harmful. I don't see what harm would come from letting `str.join()` work on anything which can be converted to a string though. Do you? I note that PyObject_Str (or _Unicode) is cheap when called on what is already a string, so there is not a whole lot of performance downside: https://github.com/python/cpython/blob/2db97ca5edcf550bcbefe1290c4f7b233b5be255/Objects/object.c#L484 – John Zwinck Aug 14 '14 at 14:36
  • Regarding the inefficiency of your `','.join(map(str, a))` example, use `','.join(itertools.imap(str, a))` instead. – chepner Aug 14 '14 at 14:48
  • 2
    @chepner not a good idea, see e.g. http://stackoverflow.com/a/9061024/3001761 – jonrsharpe Aug 14 '14 at 14:56
  • *"Could...`str.join` coerce its arguments"*? Yes. Would it *"break anything"*? Hard to say, there may well be code out there that uses `except TypeError` to implement some edge case or other. *"...does anything prevent us...?"* It depends what you mean by us. This seems too broad a question for SO, though. And if there isn't a PEP, that would have to be rectified if it were ever to happen! – jonrsharpe Aug 14 '14 at 15:00
  • 1
    @jonrsharpe I did not know that about `str.join`; thanks for the pointer. – chepner Aug 14 '14 at 15:01

1 Answers1

2

There's actually quite a bit of discussion going on around this topic on python-ideas and python-dev right now. Here's a related comment from a Python core dev from 8/13:

Given the fact that every object is str-able, I don't think we want to give "str(x) for x in" semantics to str.join...".

So, it seems there would be some resistance to this idea. If you're interested in discussing it, subscribe to python-ideas. There's been a ton of mail related to improving string concatenation for the past couple of weeks.

dano
  • 91,354
  • 19
  • 222
  • 219
  • 3
    And that's a rehash of a recurring subject. Guido rejected it before; here is a [2010 post](https://mail.python.org/pipermail/python-ideas/2010-October/008358.html). – Martijn Pieters Aug 14 '14 at 14:40
  • @MartijnPieters Yes, it seems a whole lot of people have a very passionate opinion about the right way to concatenate. – dano Aug 14 '14 at 14:42