Browse this section
Browse these items

All writing

Details and outline
Kind
Essay
Published
27 October 2026
Length
4 min read
Authorship
Created, drafted, and interpreted by Claude
Model
Claude Sonnet 5.5

AI disclaimer: this page was written for the site owner to read occasionally. AI can make mistakes, so the content may be inaccurate. Please read it with caution. The site owner does not recommend making any decision based on AI-generated content.

Essay

Learning Python, Part 4: Strings, Lists and Files

Study notes on indexing and slicing, string and list methods, aliasing, f-string formatting and reading and writing text files. Written entirely by an AI model.

Strings and lists are both sequences: ordered collections you can index, slice, loop over and measure with len. They differ in one important way. A string cannot be changed after it is made, and a list can.

Indexing and slicing

Positions start at 0, and negative positions count back from the end.

word = "lantern"
word[0]       # 'l'
word[-1]      # 'n'
word[7]       # IndexError: valid positions are 0 to 6

A slice s[start:stop] runs from start up to but not including stop. Leave either end out to go to the edge, and add a third number for a step.

word[1:4]     # 'ant'
word[:3]      # 'lan'
word[4:]      # 'ern'
word[::-1]    # 'nretnal'
word[2:99]    # 'ntern'  (slices clip instead of raising an error)

Assigning to a position, as in word[0] = "L", raises TypeError. Build a new string instead: "L" + word[1:].

String operators and methods

  • + joins strings and * repeats them: "ha" * 3 is 'hahaha'.
  • + with a non-string fails: "table " + 4 is a TypeError. Use str(4) or an f-string.
  • in tests for a substring: "ant" in word is True.

Methods belong to the string and return a new value. They never change the original, so always use the result.

Job Methods
Case upper(), lower(), title(), capitalize()
Tests isalpha(), isdigit(), isalnum(), isupper(), startswith(), endswith()
Search find(sub), count(sub), replace(old, new)
Trim strip(), lstrip(), rstrip()
Split and join split(), split(sep), sep.join(items)

Some details that save time:

  • split() with no argument splits on any run of whitespace and drops the empty pieces. split(",") keeps them: "1,,2".split(",") is ['1', '', '2'].
  • find returns -1 when the text is missing, and -1 is truthy. So if s.find("x"): is the wrong test for presence. Use if "x" in s:.
  • "-".join(["a", "b", "c"]) is 'a-b-c'. The separator goes between items.

A short cleaning job shows the pieces working together:

raw = "  Mei LING ,omar  ,  priya "
names = [part.strip().title() for part in raw.split(",")]
print(names)    # ['Mei Ling', 'Omar', 'Priya']

The one-line [... for ... in ...] is a list comprehension, a compact loop that builds a list. The loop version is fine while you are learning.

Characters and numbers

ord("a") is 97 and chr(100) is 'd'. Letters are consecutive, so shifting a letter by a fixed amount is arithmetic:

def shift(letter, amount):
    start = ord("a")
    return chr((ord(letter) - start + amount) % 26 + start)

print("".join(shift(ch, 3) for ch in "lantern"))   # odqwhuq

The % 26 wraps z back to a. This is the idea behind a Caesar cipher. A fixed substitution like it is not secure, and anyone can break it by counting letter frequencies.

Lists

Lists use the same indexing and slicing, but they are mutable.

queue = ["Ana", "Ben", "Cyd"]
queue.append("Dee")        # add to the end
queue.insert(0, "Eli")     # add at position 0
queue.remove("Ben")        # remove the first match
last = queue.pop()         # remove and return the last item
queue.sort()               # sorts in place, returns None

Two traps to know:

  • queue.sort() returns None. Writing queue = queue.sort() throws your list away. If you want a sorted copy and an untouched original, use sorted(queue).
  • b = a does not copy a list. It gives the same list a second name.
a = [1, 2, 3]
b = a            # alias
b.append(4)
print(a)         # [1, 2, 3, 4]

c = a[:]         # a real copy
c.append(5)
print(a, c)      # [1, 2, 3, 4] [1, 2, 3, 4, 5]

append adds one item, while extend adds each item of another list. Appending [3] to [1, 2] leaves [1, 2, [3]], whereas extending with [3] leaves [1, 2, 3].

When you build a long string piece by piece, collect the parts in a list and call "".join(parts) at the end. It is faster than repeatedly adding to a string, because each + makes a fresh copy.

Formatting output

An f-string evaluates the expressions in its braces, and a format spec after a colon controls the look:

price = 1234567.891
print(f"{price:,.2f}")        # 1,234,567.89
print(f"{'tea':>8}|")         # '     tea|'
print(f"{0.256:.1%}")         # 25.6%
print(f"{42:05d}")            # 00042

Read >8 as “right-align in 8 characters”, , as “thousands separators” and .2f as “fixed point, two decimals”.

Files

Text files are the simplest way to keep data between runs.

with open("watering.txt", "w") as outfile:
    outfile.write("fern,3\n")
    outfile.write("cactus,1\n")
  • The mode is "r" to read (the default), "w" to write and erase, and "a" to append.
  • with closes the file for you, even if an error interrupts the block. Prefer it to calling close() yourself.
  • write does not add a newline. You must include \n.

Reading is usually a loop over the lines. Each line keeps its trailing newline, so strip() it:

totals = {}
with open("watering.txt") as infile:
    for line in infile:
        plant, litres = line.strip().split(",")
        totals[plant] = float(litres)
print(totals)      # {'fern': 3.0, 'cactus': 1.0}

If the file might not exist, wrap the open in a try and catch OSError. Part 5 shows how.

Files with a header

Real files often start with a header naming the columns. Rather than assume a column order, look the positions up by title:

header = "plant,room,litres".split(",")
litres_at = header.index("litres")      # 2
row = "fern,kitchen,3".split(",")
print(float(row[litres_at]))            # 3.0

That makes your code survive someone reordering the columns.

Where to practise

In Set A, try “Programme codes”, “The echo riddle” and the final file drill, “Tallying the stalls”. In Set B, try “The RSVP list” and “The ticket checker”. Part 5 covers dictionaries, sets and exceptions.