Skip to content
VLSI Mentor

Python Part I · Module 4 · Strings

Joining and Repeating Strings

Two of the operators from Module 3 do something useful to text. Plus combines two strings into a longer one, and star repeats a string a given number of times — which is how you produce a divider line that is exactly as wide as the title above it. Both are simple, and both have edges worth knowing: plus adds nothing of its own, not even a space, and it refuses outright to combine text with a number. The chapter closes with the reason plus is the wrong tool once you have many pieces to assemble, an argument that comes directly from what Module 2 said about immutable values and sets up the join method later in this module.

Foundation11 min readPythonPart IFundamentalsStringsOperators

Part I · Module 4 · Chapter 4.3 · Joining and Repeating Strings

1. Plus Combines Two Strings

You already know + as addition. Applied to two strings it does something different but closely related: it produces a new string containing the characters of the first followed by the characters of the second. The word for that is concatenation.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
name = "smoke" + "_test"
print(name)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
smoke_test

It works the same way on names rather than literals, which is how it is actually used:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
prefix = "axi_"
kind = "smoke"
print(prefix + kind)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
axi_smoke

And it chains, because the result of a + is itself a string that the next + can work on:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print("runs" + "/" + "axi_smoke")
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
runs/axi_smoke

That is a normal Module 3 expression being evaluated left to right. There is nothing special happening: each + takes two strings and gives back one.

2. Plus Adds Nothing of Its Own

Here is the first thing people get wrong, and it is worth demonstrating rather than stating:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print("PASS" + "FAIL")
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
PASSFAIL

No space. Concatenation joins exactly the characters you gave it and inserts nothing. If you want a space, it has to be a character in one of the strings, or a string of its own:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print("PASS" + " " + "FAIL")
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
PASS FAIL

This is also the reason Section 6 of this chapter exists: once you are joining more than three or four pieces, putting the separators in by hand becomes both tedious and easy to get wrong. Chapter 4.9 has the tool for that case.

3. Plus Will Not Mix Text and Numbers

Chapter 3.2 already showed this, so it is a reminder rather than a lesson:

Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE
print("seed_" + 42)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
TypeError: can only concatenate str (not "int") to str

Python will not guess. "seed_" is text and 42 is a number, and there is no single obvious meaning for combining them — so rather than inventing one, Python stops.

The fix is the conversion from Chapter 2.11: turn the number into text first, and then both operands are strings.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
seed = 42
print("seed_" + str(seed))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
seed_42

That works and is perfectly correct. It is also the exact pain that f-strings remove, which is why Chapter 4.12 exists — but str() plus concatenation is the honest foundation underneath it, and you should be able to read code written this way.

4. Star Repeats a String

The other Module 3 operator that does something useful to text is *. With a string on one side and a whole number on the other, it repeats the string:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
rule = "-" * 40
print(rule)
print(len(rule))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
----------------------------------------
40

Forty hyphens, from four characters of source. len() is Chapter 4.6; here it is only confirming the count.

The order of the operands does not matter:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print(3 * "ab")
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
ababab

Both forms are valid. "ab" * 3 reads more naturally to most people — the thing first, then how many times — and that is the form you will usually see.

The idiom worth keeping

Repetition becomes genuinely useful when the count comes from the text itself. This produces an underline that is always exactly as wide as the title, however the title changes:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
title = "REGRESSION SUMMARY"
print(title)
print("=" * len(title))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
REGRESSION SUMMARY
==================

Change the title and the underline follows automatically. Compare that with typing eighteen equals signs by hand, which is correct exactly once.

5. The Edges of Star

Three cases, all verified, each teaching something.

A count of zero gives empty text. Not an error, not a single copy:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print("[" + "-" * 0 + "]")
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
[]

A negative count also gives empty text. Python treats "repeat it minus five times" as "there is nothing to repeat":

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print("[" + "-" * -5 + "]")
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
[]

That is worth knowing because it fails quietly. If a count is computed and comes out negative, you get an empty string rather than a complaint, and the missing text can be hard to trace.

The count must be a whole number. A float is refused even when it looks whole:

Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE
print("-" * 2.0)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
TypeError: can't multiply sequence by non-int of type 'float'
Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE
print("-" * "5")
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
TypeError: can't multiply sequence by non-int of type 'str'

The word sequence in that message is Python's general term for "a thing with items in order", and a string is one. The message is saying: you can repeat a sequence a whole number of times, and 2.0 is not a whole number — it is a float. As Chapter 2.6 established, 2.0 and 2 are different types even though they compare equal. Convert with int() if a count arrives as a float.

Also note what * does not do: it repeats, it does not pad.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print("[" + "ab" * 2 + "]")
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
[abab]

If you want text padded out to a fixed width so that a column lines up, that is a formatting job, and Chapter 4.13 does it properly.

6. Why Plus Is the Wrong Tool for Many Pieces

You can build a string up a step at a time. Chapter 3.3 taught +=, and it works on text exactly as you would expect:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
line = "vcs"
line += " -full64"
line += " -f files.f"
print(line)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
vcs -full64 -f files.f

That is fine. Three pieces, three lines, perfectly readable.

Now the part the canonical curriculum wants you to understand, because it is a real cost and not a style preference.

Recall from Chapter 2.13 that a string cannot be modified. So line += " -full64" is not appending anything to the existing string. It cannot. What actually happens is:

  1. a new string is built, long enough to hold both parts;
  2. every character of the old line is copied into it;
  3. every character of " -full64" is copied after them;
  4. the name line is rebound to that new string;
  5. the old string is now unused.

For three pieces that is trivial. But notice what the cost depends on: step 2 copies everything accumulated so far. Build a 500-line report one line at a time and the first line gets copied 500 times, the second 499 times, and so on. The work grows out of proportion to the amount of text — you are not doing 500 units of work, you are doing something closer to 125,000.

You will meet the tempting version of this mistake in Module 10, where repeating an action many times becomes easy. The reason not to do it is here, in immutability, and it is worth carrying forward: repeated concatenation is not slow because Python is slow. It is slow because each step rebuilds everything.

7. Predict, Run, Observe

Predict all five before reading on.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print("a" + "b" + "c")
print("ab" * 3)
print("-" * 0 + "end")
print(len("ab" * 4))
print("x" + "y" * 3)

The verified output:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
abc
ababab
end
8
xyyy

The first four should be straightforward. The fifth is the one to check yourself on: the answer is xyyy, not xyxyxy. Precedence decides it — Chapter 3.8 established that * binds tighter than +, so "y" * 3 happens first and the result is concatenated onto "x". If you want the other meaning you must say so:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print(("x" + "y") * 3)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
xyxyxy

Which is exactly the argument Chapter 3.8 made: where a reader would have to work out the order, put the brackets in.

8. Exercises

Exercise 1 — build a path. Using only +, build and print the string runs/axi_smoke/sim.log from three names: base = "runs", test = "axi_smoke", filename = "sim.log". Count the separators you had to supply yourself.

Exercise 2 — the missing space. This prints axi_smokePASS. Fix it two different ways — once by changing a literal, once by adding an operand:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
test = "axi_smoke"
status = "PASS"
print(test + status)

Exercise 3 — predict, then run. Give the output of each without running it: (a) "=" * 5 (b) 5 * "=" (c) "=" * 1 (d) "ab" + "ab" (e) "ab" * 2 (f) len("--" * 10)

Exercise 4 — the underline. Write a two-line output where the second line underlines the first with -, and the underline is exactly the right width for any title. Then change the title to something longer and confirm you did not have to touch the second line.

Exercise 5 — read the error. A colleague's script fails with TypeError: can only concatenate str (not "int") to str on this line. Explain which operand is at fault and give two different corrected versions:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print("runtime: " + 182)

Exercise 6 — explain the cost. In two or three sentences, and without using the word "loop", explain why assembling a thousand-line report with += does much more work than assembling a three-line one, and name the method this module provides instead.

9. Summary

  • + on strings concatenates: the characters of the left operand followed by those of the right.
  • + inserts nothing of its own. Every separator must be a character you supplied.
  • + will not mix text and numbers — TypeError: can only concatenate str (not "int") to str. Convert with str() first, as Chapter 2.11 showed.
  • * repeats a string a whole number of times, in either operand order.
  • "=" * len(title) is the idiom worth keeping — an underline derived from the text rather than typed out.
  • A zero or negative count gives an empty string, quietly. A float or string count is a TypeError.
  • * repeats, it does not pad. Padding to a fixed width is Chapter 4.13.
  • * binds tighter than +, so "x" + "y" * 3 is xyyy. Bracket it if a reader would have to think.
  • Each += rebuilds the whole string, because strings are immutable. Fine for a few pieces; the wrong tool for many. join in Chapter 4.9 is the right one.

You can now write text and combine it. The next chapter goes the other way, and reaches inside a string to a single character.

Where this fits

Part of the Python curriculum.