On this page

Strings

You have used text since the first module, as colour names and as words to print. So far a piece of text has been one whole thing. In this module you open it up: a string is a row of characters, each with a position, and you can take pieces out of it, walk along it, search it and build a new one.

Before this, you can: write a function that returns a value; loop with range and use the loop variable; tell a number from text.

By the end you will be able to pick out a character or a piece of a string, loop over its characters, ask whether one piece of text is inside another, use methods that give back a new string, build a string step by step, and put numbers into text with an f-string.

Before you read on, decide what this prints:

title = "the sea"
title.upper()
print(title)
the sea

If you expected THE SEA, you are in good company. title.upper() does make "THE SEA". But it makes it as a new string and hands it back, and this program does nothing with what it was handed. title is still the string it always was. A string is never changed in place, in Python as in Java. Most of this module follows from that.

Text has positions

A string is a row of characters. Each has a position, counted from 0:

 p   l   a   n   e   t
 0   1   2   3   4   5

Square brackets pick out one character, and len counts them all:

word = "planet"
print(word[0], word[5], len(word))
p t 6

The last position is always one less than the length, because counting starts at 0. Asking for a position that is not there is an error:

word = "planet"
print(word[6])
  File "your_program.py", line 2
    print(word[6])
IndexError: string index out of range

What you get from word[0] is itself a string, one character long. Python has no separate type for a single character.

Two strings are compared with ==, and it compares the text itself, character by character. "cat" == "cat" is True and "Cat" == "cat" is False, because a capital letter is a different character.

From the end, and in pieces

A negative position counts from the end: word[-1] is the last character, word[-2] the one before it.

Two positions with a colon between them take a piece, called a slice. word[1:4] starts at position 1 and stops before position 4:

word = "planet"
print(word[-1])
print(word[1:4])
print(word[:2])
print(word[3:])
t
lan
pl
net

Leave out the first number and the slice starts at the beginning. Leave out the second and it runs to the end. A useful way to read word[1:4] is to think of the numbers as marking the gaps between the tiles: cut at gap 1 and at gap 4, and take what is between.

   p   l   a   n   e   t
 0   1   2   3   4   5   6

That is why word[:2] and word[2:] together give back the whole word, with nothing lost and nothing twice. It is also why the length of word[1:4] is 4 − 1.

A slice that reaches past the end is not an error; it just stops at the end. word[4:100] is "et".

One character at a time

A for loop can walk along a string directly. The loop variable is given each character in turn:

for ch in "sun":
    print(ch)
s
u
n

There is no need for range here, and no position to get wrong. Use this form when you only need the characters.

When you need the position as well, loop over the positions and look each character up:

word = "sun"
for i in range(len(word)):
    print(i, word[i])
0 s
1 u
2 n

Either loop can draw. Here each character gets a tile:

from scimigo import canvas, rectangle, text

canvas(600, 400)
word = "sun"
for i in range(len(word)):
    rectangle(40 + i * 70, 160, 60, 60, color="khaki")
    text(58 + i * 70, 202, word[i], size=32)
sun

Is it in there?

in asks whether one string appears inside another, as a run of characters next to each other. The answer is True or False:

print("an" in "planet")
print("p" in "Planet")
print("ant" in "planet")
True
False
False

"an" is there, at positions 2 and 3. "p" is not in "Planet", which has a capital P. And "ant" is not there although all three letters are, because they are not next to each other in that order.

in is often the shortest way to test a character against several possibilities. ch in "aeiou" is True when ch is any one of the five vowels.

Methods give you a new string

A method is a function that belongs to a value, called with a dot. Strings have many. Three useful ones:

messy = "  Hello_World  "
print(messy.strip())
print(messy.lower())
print(messy.replace("_", " "))
print(messy)
Hello_World
  hello_world  
  Hello World  
  Hello_World

strip takes the spaces off both ends, lower makes every letter lower case, and replace swaps one piece of text for another wherever it appears. Look at the last line: after all three calls, messy is exactly what it was. Each method made a new string and handed it back. None of them changed messy, because a string cannot be changed.

So a method call on a line of its own does nothing useful. To keep the result, give it a name. To apply several steps, keep each result and work on that:

messy = "  Hello_World  "
tidy = messy.strip()
tidy = tidy.lower()
tidy = tidy.replace("_", " ")
print(tidy)
hello world

This is the same lesson as in Functions: a value that is handed back and not kept is lost.

Building text

Since a string cannot be changed, a longer one is made by joining: + puts two strings end to end and gives a new string. Doing that in a loop builds a result piece by piece, the same way a running total is built:

result = ""
for ch in "abc":
    result = result + ch + "-"
print(result)
a-b-c-

result starts as the empty string, "", which plays the part that 0 plays in a total. On each turn a new, longer string is made and the name result is moved to it.

The order matters. result + ch adds at the end; ch + result adds at the front, which builds the text backwards.

Numbers into text, and back

+ joins two strings or adds two numbers. It will not mix them:

score = 7
print("Score: " + score)
  File "your_program.py", line 2
    print("Score: " + score)
TypeError: can only concatenate str (not "int") to str

Python will not guess whether you meant the text "7" or the number 7. str makes text from a number, and int makes a whole number from text that looks like one:

print("Score: " + str(7))
print(int("12") + 1)
print("12" + "1")
Score: 7
13
121

Most of the time there is a better tool. Put the letter f in front of the opening quote, and anything inside curly brackets is worked out and placed in the text:

name = "Ada"
width = 3
height = 4
print(f"{name} drew {width} by {height}, area {width * height}.")
Ada drew 3 by 4, area 12.

This is an f-string. The brackets can hold a name or a whole calculation, and numbers need no str. When you want to print or draw a mixture of text and values, reach for an f-string first.

In the lab

You will read characters and slices before running them, put every letter of a word on its own tile, decide what in answers, find the line that throws a result away, tidy a messy string in three steps, follow a result as it grows, and then write functions that count vowels and hide all but the last four characters of a code.

Your turn

Now try it yourself

Predict what a program will do, run it, and step through it line by line. The checks tell you when your own code works.

Loading the lab…

In this lab

  1. Which character?

    A string is a row of characters with positions counted from 0. Decide what each line of this program does before you run it. One of the lines fails.

  2. From the end, and a piece

    A negative position counts from the end. Two positions with a colon take a piece, which stops before the second position. Picture the letters of planet on six tiles numbered 0 to 5, and decide what each line prints.

  3. Letter tiles

    This program draws one tile, for the first letter of word. Change it so that it draws a tile for every letter, whatever the word is.

    • Tile number i is a square of side 60 at x = 40 + 70 × i, y = 160, coloured "khaki".
    • Its letter is written at x = 58 + 70 × i, y = 202, with size=32.

    The checks try other words, shorter and longer.

  4. Is it in there?

    in asks whether one string appears inside another. == asks whether two strings are the same text. Each line prints True or False. Decide which.

  5. Did it change?

    upper makes an upper-case version of a string. This program calls it twice, in two different ways. Decide what each print shows.

  6. Tidy up

    messy has spaces at both ends, capital letters, and underscores where spaces should be. The program should print the tidy version: for the text given, hello big world.

    Clean it in three steps, keeping each result in tidy:

    1. take the spaces off both ends;
    2. make it lower case;
    3. replace every underscore with a space.

    The last line already prints tidy. The checks try other messy texts.

  7. Growing a result

    This loop builds a string one character at a time. Follow ch and result through the three turns, then decide what is printed.

  8. Text and numbers

    Four short programs about mixing text and numbers. Decide what each one does.

  9. Count the vowels

    Write count_vowels(text). It returns how many characters of text are vowels: a, e, i, o or u, in either case. It prints nothing.

    The last line of the program then prints the count for Hello World, which is 3.

  10. Hide all but the last four

    Receipts hide most of a card number. Write mask(code), which returns code with every character replaced by a star, *, except the last four. A code of four characters or fewer comes back unchanged. The function prints nothing.

    For example, mask("12345678") is ****5678.

  11. Username

    A school makes usernames from names. Write username(first, last), which returns:

    • the first letter of first, followed by all of last;
    • in lower case;
    • with any spaces removed;
    • cut to at most 8 characters.

    So username("Ada", "Lovelace") is alovelac, and username("Grace", "Hopper") is ghopper.

  12. Where is it?

    Print every position at which letter appears in sentence, one position per line, in order. If it does not appear at all, print one line: not found.

    For the values given, the program prints 1, 3, 5 and 10.

  13. The title that stays small

    This program is meant to print the title in capital letters: THE OLD MAN AND THE SEA. It prints it exactly as it was.

    Before you change anything, say to yourself which line makes the capitals and what happens to them. Then fix the program. The checks try other titles.

  14. Vowel chart

    Draw a bar chart of how often each vowel appears in sentence, which is in lower case.

    1. Write count_letter(text, letter), which returns how many times letter appears in text.
    2. For each of the five vowels, in the order a, e, i, o, u, with i going from 0 to 4:
      • draw a "teal" bar 60 wide at x = 60 + 100 × i. Its height is 20 times the count, and its bottom edge is at y = 300, so its top is at y = 300 − 20 × the count;
      • write a label at x = 60 + 100 × i, y = 330: the vowel, a colon, a space and the count, as in e: 3. An f-string is the shortest way to make it, and joining with str works too; the check looks only at the text.

    A vowel that does not appear still gets a label, and a bar of height 0.