If you study computer science in Year 3 of the applied-sciences option of the liceo scientifico, with two hours a week, between November and January the syllabus gets to strings and files, right after loops and functions. The test is usually a practical lab exam, five to nine weeks from today: a text to read, a program to write and run. This is the right moment to practise, because a practical test is not prepared by rereading: it is prepared by writing code with your hands on the keyboard.
Here you will find the rules for strings, the methods you really need, reading and writing files and three exercises with complete code and output. I ran every line: you can copy and try. If Python is still new to you, start from learning Python from scratch.
Strings are immutable sequences
A string is a sequence of characters, and each character has an index that starts at 0. Negative indices count from the end: -1 is the last character.
phrase = "Python is great"
print(phrase[0]) # P
print(phrase[-1]) # t
print(phrase[2:5]) # tho
print(phrase[::-1]) # taerg si nohtyP
Slicing s[a:b] takes from character a up to b excluded. The third value is the step: [::-1] runs through the string backwards and reverses it.
Strings are immutable: you cannot write phrase[0] = "J", Python gives TypeError. To change something you build a new string and assign it to a variable.
The methods to know
| Method | What it does | Example |
|---|---|---|
upper() / lower() | upper case / lower case | "hello".upper() → 'HELLO' |
strip() | removes spaces and \n at the ends | " hello ".strip() → 'hello' |
split() | splits into a list | "a b c".split() → ['a', 'b', 'c'] |
replace(a, b) | replaces | "banana".replace("a", "o") → 'bonono' |
find(x) | index of the first occurrence, -1 if absent | "Python is great".find("is") → 7 |
separator.join(list) | joins a list | "-".join(["a","b","c"]) → 'a-b-c' |
Every method returns a new string and does not modify the original one: if you write only s.upper() without assigning the result, nothing happens to your s. It is one of the most frequent mistakes in the lab.
To visit the characters you use a for loop:
def vowels(s):
n = 0
for c in s.lower():
if c in "aeiou":
n += 1
return n
print(vowels("Programming")) # 3
The vowels in “Programming” are o, a, i: three. The loop for c in s gives each character, with no need for indices, and the form c in "aeiou" checks whether the character appears in the string.
The Caesar cipher with ord and chr
ord(c) returns the numeric code of a character, chr(n) does the opposite: ord("a") is 97, chr(100) is 'd'. With these two you shift a letter by k places:
def caesar(text, k):
result = ""
for c in text:
if "a" <= c <= "z":
new = (ord(c) - ord("a") + k) % 26 + ord("a")
result += chr(new)
else:
result += c
return result
print(caesar("hello world", 3)) # khoor zruog
The key step is % 26: it shifts the letter without leaving the alphabet, and so x with k = 3 becomes a. Spaces and symbols are not letters and pass through unchanged. The cipher is also explained from the maths side in cryptography: Caesar, Vigenère, RSA.
Working with files
The correct way to open a file is with, which closes it by itself at the end of the block:
with open("grades.txt") as f:
for line in f:
print(line.strip())
The loop for line in f reads one line at a time, and every line carries with it the newline character \n: that is why you almost always need strip(). There are three opening modes:
"r"(default): reading. If the file does not exist, error."w": writing. If the file exists, it empties it immediately."a": appending at the end, without touching the contents.
If you need all the contents at once, f.read() returns a single string, while f.readlines() returns a list with one string per line, \n included. For small files both are fine; the line-by-line loop remains the tidiest choice and also works with large files.
To write you use f.write(text), and here too the \n has to be added by hand: f.write("Anna\n"). A file that does not exist is handled like this:
try:
with open("grades.txt") as f:
content = f.read()
except FileNotFoundError:
print("File not found")
Exercise 1: palindrome and anagram
Write a function that says whether a sentence is a palindrome (it reads the same from right to left, ignoring spaces and capitals) and one that says whether two words are anagrams.
def is_palindrome(s):
clean = s.replace(" ", "").lower()
return clean == clean[::-1]
def is_anagram(a, b):
return sorted(a.lower()) == sorted(b.lower())
print(is_palindrome("Anna")) # True
print(is_palindrome("Was it a car or a cat I saw")) # True
print(is_palindrome("hello")) # False
print(is_anagram("Listen", "Silent")) # True
print(is_anagram("house", "horse")) # False
For the palindrome I remove the spaces with replace, put everything in lower case and compare the string with its reversed version. For the anagram sorted turns each word into a list of sorted letters: two words are anagrams if, once sorted, they give the same list. “listen” and “silent” both give ['e','i','l','n','s','t']; “house” and “horse” do not, because one has a u where the other has an r.
Exercise 2: words and longest line of a file
The file words.txt contains three lines. Count the total words and find the longest line.
the cat sleeps
on the sofa today
it rains
n_words = 0
longest = ""
with open("words.txt") as f:
for line in f:
line = line.strip()
n_words += len(line.split())
if len(line) > len(longest):
longest = line
print("Words:", n_words)
print("Longest line:", longest, "(", len(longest), "characters )")
Output:
Words: 9
Longest line: on the sofa today ( 17 characters )
The lines have 3, 4 and 2 words: 9 in all. “on the sofa today” has 2 + 1 + 3 + 1 + 4 + 1 + 5 = 17 characters, counting the spaces, and is longer than “the cat sleeps”, which has 14. The strip() comes before the count: without it, every line would have one extra character for the \n, and the result would be wrong, 15 instead of 14 for the first line.
Exercise 3: average of grades read from a file
The file grades.txt contains, for each student, the name and three grades separated by commas. Print the average of each and the average of all the grades.
Anna,7,8,6
Marco,5,6,7
Sara,9,8,10
total = 0
count = 0
try:
with open("grades.txt") as f:
for line in f:
fields = line.strip().split(",")
name = fields[0]
grades = [int(x) for x in fields[1:]]
avg = sum(grades) / len(grades)
print(name, round(avg, 2))
total += sum(grades)
count += len(grades)
print("Overall average:", round(total / count, 2))
except FileNotFoundError:
print("File not found")
Output:
Anna 7.0
Marco 6.0
Sara 9.0
Overall average: 7.33
Each line is split on the commas: fields[0] is the name, fields[1:] are the grades, still strings, so they have to be converted with int. Anna: 21 / 3 = 7; Marco: 18 / 3 = 6; Sara: 27 / 3 = 9. The overall average is 66 / 9 = 7.33. The sums accumulate outside the loop, otherwise the value resets on every line.
The mistakes that cost marks in the lab
- Forgetting the
\n: when reading, not removing it withstrip()distorts lengths and comparisons; when writing, without\nall the lines end up stuck together. - Modifying a string in place:
s[0] = "x"does not work, ands.upper()without assignment does not changes. - Opening in
"w"a file you wanted to read or complete: it empties it before you even write. To append you use"a". - Index out of range:
s[len(s)]does not exist, the last valid index islen(s) - 1. Withfor c in sthe problem does not arise. - Empty lines at the end of the file:
"".split(",")gives['']andint('')givesValueError. If the file has an empty last line, check firstif line.strip():.
For nested loops and the use of indices, which are taken as known here, there is loops and arrays in Year 3 computer science; the functions used above are in passing parameters, and for those who want the next step, recursion, factorial and Fibonacci. The page subjects: computer science explains how I work.
Simulator and next step
For computer science there is no dedicated simulator: in the practice tests for the liceo you will find maths and physics tests, so it is not the right category for this test. The best way to prepare is to redo the three exercises without looking, changing the data: another file, another sentence, an extra column.
If the lab test frightens you, write to me through the contact page: the free 30-minute introductory call is where we look together at where you get stuck.