69

I am reading The Hitchhiker’s Guide to Python and there is a short code snippet

foo = 'foo'
bar = 'bar'

foobar = foo + bar  # This is good
foo += 'ooo'  # This is bad, instead you should do:
foo = ''.join([foo, 'ooo'])

The author pointed out that ''.join() is not always faster than +, so he is not against using + for string concatenation.

But why is foo += 'ooo' bad practice whereas foobar=foo+bar is considered good?

  • is foo += bar good?
  • is foo = foo + 'ooo' good?

Before this code snippet, the author wrote:

One final thing to mention about strings is that using join() is not always best. In the instances where you are creating a new string from a pre-determined number of strings, using the addition operator is actually faster, but in cases like above or in cases where you are adding to an existing string, using join() should be your preferred method.

Jacob Vlijm
  • 3,099
  • 1
  • 21
  • 37
nos
  • 19,875
  • 27
  • 98
  • 134
  • 2
    @jonrsharpe: that question doesn't actually cover the *single augmented assignment case* outside of a loop. I'm frankly quite surprised by that claim in the guide, because there is no technical difference between `foo + bar` and `foo += bar`, but apparently there is for `foo += 'ooo'`.. – Martijn Pieters Sep 24 '16 at 11:43
  • @jonrsharpe: I think this is not a duplicate. There the issue is speed of `+` versus `''.join()`. Here it's comparing two ways of using `+`. – nos Sep 24 '16 at 11:58
  • 1
    I think the reasoning in the guide is that for string _creation_ `str.join()` is not always better, `foobar = ''.join(foo, bar)` isn't really better than `foobar = foo + bar`. If you look at the whole [context](http://docs.python-guide.org/en/latest/writing/structure/#mutable-and-immutable-types) of the statement it's clearer that it is ment as an exceptoin for the advise that `join()` is preferable to `+=` in most cases. The given example could probably be improved. – mata Sep 24 '16 at 12:09
  • 5
    `foo = ''.join([foo, 'ooo'])` seems very overkill in this example. Not only is it less readable but also 100 times slower than the other examples, according to some tests with the timeit-module. – Ted Klein Bergman Sep 24 '16 at 12:19
  • 1
    I don't see anything inherently wrong with `foo += 'ooo'`... It's important to point out that the author of the Hitchhiker's Guide refers to "good" and "bad" in terms of performance: *it is much more efficient to accumulate the parts in a list, which is mutable, and then glue (‘join’) the parts together when the full string is needed* – Carlos Mermingas Sep 24 '16 at 13:05
  • whatever is more readable. Join for lots of items, + for two. – Paul Collingwood Sep 24 '16 at 14:40
  • You need to read [Why is ''.join() faster than += in Python](http://stackoverflow.com/questions/39312099/why-is-join-faster-than-in-python) – vishes_shell Sep 24 '16 at 20:53

2 Answers2

93

Is it bad practice?

It's reasonable to assume that it isn't bad practice for this example because:

  • The author doesn't give any reason. Maybe it's just disliked by him/her.
  • Python documentation doesn't mention it's bad practice (from what I've seen).
  • foo += 'ooo' is just as readable (according to me) and is approximately 100 times faster than foo = ''.join([foo, 'ooo']).

When should one be used over the other?

Concatenation of strings have the disadvantage of needing to create a new string and allocate new memory for every concatenation! This is time consuming, but isn't that big of a deal with few and small strings. When you know the number of strings to concatenate and don't need more than maybe 2-4 concatenations I'd go for it.


When joining strings Python only has to allocate new memory for the final string, which is much more efficient, but could take longer to compute. Also, because strings are immutable it's often more practical to use a list of strings to dynamically mutate, and only convert it to a string when needed.

It's often convenient to create strings with str.join() since it takes an iterable. For example:

letters = ", ".join("abcdefghij")

To conclude

In most cases it makes more sense to use str.join() but there are times when concatenation is just as viable. Using any form of string concatenation for huge or many strings would be bad practice just as using str.join() would be bad practice for short and few strings, in my own opinion.

I believe that the author was just trying to create a rule of thumb to easier identify when to use what without going in too much detail or make it complicated.

Ted Klein Bergman
  • 9,146
  • 4
  • 29
  • 50
  • 4
    `", ".join(name for name in school)` is the same as `", ".join(school)`, the extra generator expression doesn't improve readability and only makes it _less_ efficient. Unless you need to process `name` (modify, filter, index, ...) there's no reason to use a generator expression – mata Sep 25 '16 at 13:02
  • Yes, you're absolutely right! It was a mistake on my part and I'll change the example. – Ted Klein Bergman Sep 25 '16 at 13:55
  • @TedKleinBergman the `", ".join(range(10))` probably isn't the best example as it'll fail... – Jon Clements Sep 25 '16 at 14:05
  • @JonClements Yeah, I don't know what I was thinking. I'm a bit busy/stressed at the moment, but I'll make sure to add a better example later – Ted Klein Bergman Sep 25 '16 at 14:08
  • 1
    @TedKleinBergman no worries... maybe show it using `letters = ', '.join('abcdefghij')` or something... gets the point across... – Jon Clements Sep 25 '16 at 14:10
  • @JonClements That's an great example! Will quickly add it. Thanks! – Ted Klein Bergman Sep 25 '16 at 14:15
-4

If the number of string is small and strings are known in advance, I would go :

foo = f"{foo}ooo"

Using f-strings. However, this is valid only since python 3.6.

  • 10
    The question was not looking for "how to concatenate strings". It was about "*why is `foo += 'ooo'` bad practice*". – Gino Mempin May 11 '21 at 06:50