Unit 3: Strings and Lists; Tuples and Dictionaries

ECE181 — Introduction To Python 6 min read

Python organises data into sequences and mappings. This unit covers three sequence types (strings, lists, tuples) and one mapping type (dictionaries), examining how each stores values, how you access and modify them, and which operations each supports.

  • Compound data type: a type built from smaller pieces you can access individually, unlike an integer or float which is atomic.
  • Indexing convention: all sequences are zero-based; the first item is at index 0, the last at index len(x) - 1, and negative indices count from the end (-1 is the last).
  • Mutability: lists and dictionaries are mutable (changeable in place); strings and tuples are immutable (any "change" builds a new object).
  • Iterability: all four types can be traversed with a for loop.
  • Membership: the in operator tests presence in any of the four types.

II. Strings — Immutable Sequences of Characters

A. String as a compound data type

A string is a sequence of characters accessible one at a time by index.

  • Element access: fruit = "banana"; fruit[1] yields 'a', not 'b', because indexing starts at 0.
  • Character values: each element is itself a one-character string; Python has no separate character type.
  • Immutability: fruit[0] = 'B' raises TypeError; build a new string instead with 'B' + fruit[1:].

B. Length

The len function returns the number of characters.

  • Usage: len("banana") returns 6.
  • Last index: the final character is fruit[len(fruit) - 1], i.e. fruit[5]; fruit[len(fruit)] is an error.

C. String traversal

Traversal visits every character in turn.

  • Index loop: step through positions.
    PYTHON
      index = 0
      while index < len(fruit):
          print(fruit[index])
          index += 1
  • For loop: cleaner idiom that needs no counter.
    PYTHON
      for char in fruit:
          print(char)

D. String slices

A slice extracts a substring using [start:stop].

  • Range: s[n:m] returns characters from index n up to but not including m; "banana"[1:4] is "ana".
  • Defaults: omit start for the beginning (s[:3]) and stop for the end (s[3:]); s[:] copies the whole string.

E. Comparison

Relational operators compare strings lexicographically.

  • Equality: "apple" == "apple" is True.
  • Ordering: comparison uses character codes, so uppercase letters precede lowercase ("Zebra" < "apple" is True because 'Z' is 90 and 'a' is 97).

F. The find function

find locates a substring or character.

  • Return value: "banana".find("na") returns 2, the index of the first match; a failed search returns -1.
  • Optional start: "banana".find("a", 3) begins searching at index 3 and returns 5.

G. Looping and counting

A loop with a counter tallies occurrences.

  • Pattern: initialise a count, increment on each match.
    PYTHON
      count = 0
      for char in "banana":
          if char == "a":
              count += 1
      print(count)   # 3

III. Lists — Mutable Sequences

A. List values

A list holds an ordered collection of values of any type, written in square brackets.

  • Mixed contents: [1, "hi", 3.0, [2, 4]] mixes integers, a string, a float, and a nested list.
  • Empty list: [] is a valid list of length zero.

B. Length

len counts top-level elements only.

  • Usage: len([1, 2, 3]) returns 3.
  • Nested counting: len([1, [2, 3], 4]) returns 3, not 4; the inner list counts as one element.

C. Membership

in and not in test for element presence.

  • Examples: 3 in [1, 2, 3] is True; 5 not in [1, 2, 3] is True.

D. Operations

+ and * combine and repeat lists.

  • Concatenation: [1, 2] + [3, 4] gives [1, 2, 3, 4].
  • Repetition: [0] * 3 gives [0, 0, 0], useful for initialising fixed-size lists.

E. Slices

Slicing works exactly as with strings.

  • Extraction: [10, 20, 30, 40][1:3] returns [20, 30].
  • Slice assignment: because lists are mutable, L[1:3] = [99] replaces that span in place.

F. Deletion

Elements are removed by index, value, or slice.

  • del by index: del L[1] removes the second element.
  • del by slice: del L[1:3] removes a range.
  • remove by value: L.remove(20) deletes the first occurrence of 20.
  • pop: L.pop() removes and returns the last element; L.pop(0) removes the first.

G. Accessing elements

Indexing reads or writes a single element.

  • Read: L[0] returns the first element.
  • Write: L[0] = 100 replaces it in place, legal only because lists are mutable.
  • Negative index: L[-1] reads the last element.

H. List and for loops

for iterates directly over elements.

  • Value loop: for x in L: print(x) visits each value.
  • Index loop: for i in range(len(L)): L[i] *= 2 doubles each element by position, needed when you must modify in place.

I. List parameters and nested list

Lists passed to functions are shared, and lists can contain lists.

  • Aliasing: a function receives a reference, so modifying the list inside changes the caller's list.
    PYTHON
      def add_zero(lst):
          lst.append(0)
      nums = [1, 2]
      add_zero(nums)     # nums is now [1, 2, 0]
  • Nested access: in m = [[1, 2], [3, 4]], m[1][0] yields 3 — first select the sublist, then index within it.

IV. Tuples — Immutable Sequences

A. Tuples

A tuple is an ordered, immutable sequence written with parentheses.

  • Creation: t = (1, 2, 3); parentheses are optional, so t = 1, 2, 3 works too.
  • Singleton: a one-element tuple needs a trailing comma: (5,), since (5) is just the integer 5.
  • Immutability: t[0] = 9 raises TypeError; use tuples for fixed records that must not change.
  • Assignment: tuple assignment swaps without a temporary — a, b = b, a.

B. Operations on tuples

Tuples support the same read operations as other sequences.

  • Indexing and slicing: t[0] returns 1; t[1:] returns (2, 3).
  • Concatenation and repetition: (1, 2) + (3,) gives (1, 2, 3); (0,) * 2 gives (0, 0).
  • Membership and length: 2 in t is True; len(t) returns 3.

V. Dictionaries — Mutable Mappings

A. Creating dictionary

A dictionary maps unique keys to values, written with braces.

  • Literal: eng2sp = {"one": "uno", "two": "dos"}.
  • Empty: d = {} or d = dict().
  • Keys: must be immutable (strings, numbers, tuples); values may be anything.

B. Adding, modifying, retrieving dictionary values

Keys index the dictionary for both reading and writing.

  • Add: eng2sp["three"] = "tres" inserts a new pair.
  • Modify: assigning to an existing key overwrites it — eng2sp["one"] = "UNO".
  • Retrieve: eng2sp["two"] returns "dos"; a missing key raises KeyError.
  • Safe retrieve: eng2sp.get("four", "?") returns "?" instead of raising.

C. Deleting items

del and pop remove pairs.

  • del: del eng2sp["one"] removes that key and value.
  • pop: eng2sp.pop("two") removes the key and returns its value "dos".
  • clear: eng2sp.clear() empties the dictionary.

D. Dictionary methods

Built-in methods expose the contents.

  • keys: d.keys() returns a view of all keys.
  • values: d.values() returns a view of all values.
  • items: d.items() returns key–value pairs as tuples, ideal for looping:
    PYTHON
      for k, v in eng2sp.items():
          print(k, "->", v)

E. Operations on dictionary

Common tests and traversals apply.

  • Length: len(eng2sp) counts key–value pairs.
  • Membership: in tests keys, not values — "one" in eng2sp is True.
  • Traversal: for k in eng2sp: iterates over keys; combine with eng2sp[k] to reach values.
  • Unordered by design: dictionaries are keyed, not positional, so you never index them by an integer position.