11. Lists Deep Dive

Python lists are ordered, mutable, and versatile sequences that can hold any mix of types, including other lists. Because they are dynamic, you can grow and shrink them, reorder items, and modify elements in place. This deep dive explains creation, indexing and slicing, core operations, the full set of common methods, comprehensions, nested lists, performance notes, and best practices—enough detail for a stand‑alone website page.

1. Creating Lists

# Literal and constructor
nums = [1, 2, 3]
empty = []
mixed = [1, ‘apple’, 3.14, True]
from_tuple = list((10, 20, 30))

# From iterables / generators
letters = list(‘spam’)            # [‘s’,’p’,’a’,’m’]
rng = list(range(5))              # [0,1,2,3,4]

# From text
line = ‘a,b,c’
parts = line.split(‘,’)           # [‘a’,’b’,’c’]

  • Lists preserve insertion order (since Python 3.7 language guarantee).
  • They are mutable: assignment to elements and slices is allowed.

2. Indexing and Slicing

Indexing starts at 0; negative indices count from the end. Slicing returns a new list. Strides allow stepping and reversal.

row = [10, 20, 30, 40, 50]
first = row[0]      # 10
last  = row[-1]     # 50
sub   = row[1:4]    # [20, 30, 40]
step  = row[::2]    # [10, 30, 50]
rev   = row[::-1]   # [50, 40, 30, 20, 10]

# Slice assignment and deletion (mutating in place)
row[1:3] = [21, 31, 32]   # [10, 21, 31, 32, 40, 50]
del row[2:4]              # [10, 21, 40, 50]

  • Slicing copies elements into a new list; modifying the slice result does not affect the source.
  • Assigning to a slice can insert, remove, or replace multiple items at once.

3. Iterating Patterns

Python offers clear idioms for looping over lists:

items = [‘a’, ‘b’, ‘c’]

# Loop values directly
for x in items:
    print(x)

# Loop with indexes
for i, x in enumerate(items):
    print(i, x)

# Reverse order
for x in reversed(items):
    print(x)

4. Core Operations

Useful built‑ins and operators:

vals = [3, 1, 4, 1, 5]
length = len(vals)               # 5
exists = 4 in vals               # True
combined = [1, 2] + [3, 4]       # [1,2,3,4]
repeated = [‘ha’] * 3            # [‘ha’,’ha’,’ha’]
mn, mx, total = min(vals), max(vals), sum(vals)  # 1, 5, 14
any_pos = any(v > 0 for v in vals)              # True
all_pos = all(v > 0 for v in vals)              # False

# Copying vs aliasing
alias = vals             # same object
copy1 = vals[:]          # shallow copy
copy2 = list(vals)       # shallow copy
copy3 = vals.copy()      # shallow copy

  • Appending with .append is amortized O(1); inserting/removing in the middle is O(n).
  • Membership checks (x in list) are O(n); for faster membership use a set when appropriate.

5. Common List Methods

These are the methods you will use most often:

Method

What it does

Notes

append(x)

Add x to the end

Mutates in place; returns None

extend(iterable)

Append all items from iterable

Use to concatenate efficiently

insert(i, x)

Insert x at index i

Shifts items right; O(n)

remove(x)

Remove first x

Raises ValueError if not found

pop([i])

Remove & return item at i

Default last item; raises IndexError if empty

clear()

Remove all items

List becomes empty

index(x[, start[, end]])

First index of x

Raises ValueError if not found

count(x)

Number of occurrences of x

 

sort(*, key=None, reverse=False)

Sort in place

Stable; returns None

reverse()

Reverse in place

Returns None

copy()

Shallow copy

Same as list(a) or a[:]

6. Sorting In Depth

 

Use list.sort() to sort in place, or sorted(iterable) to produce a new list. Both accept key and reverse.

names = [‘Alice’, ‘bob’, ‘Carol’]
# New sorted copy
print(sorted(names))                       # [‘Alice’, ‘Carol’, ‘bob’]
# Case-insensitive
print(sorted(names, key=str.lower))        # [‘Alice’, ‘bob’, ‘Carol’]
# In place reverse alphabetical
names.sort(key=str.lower, reverse=True)    # [‘Carol’, ‘bob’, ‘Alice’]

  • Python sorting is stable: equal keys keep original order (useful for multi‑key sorts).
  • For complex keys, compose tuples: sorted(records, key=lambda r: (r.city, r.name))

7. List Comprehensions

Comprehensions map, filter, and transform data concisely and efficiently:

# Map
squares = [x*x for x in range(10)]

# Filter
evens = [x for x in range(20) if x % 2 == 0]

# Map + filter
caps = [s.title() for s in [‘alice’, ‘BOB’, ‘Carol’] if len(s) >= 3]

# Nested loops (Cartesian product)
pairs = [(i, j) for i in range(2) for j in range(3)]

# Conditional expression inside
labels = [‘even’ if x % 2 == 0 else ‘odd’ for x in range(6)]

  • Prefer a simple, readable comprehension over a multi‑line loop when it fits on one line.
  • Avoid nesting more than two loops/conditions in a single comprehension—use regular loops for clarity.

8.Nested Lists (2‑D and Beyond)

Lists can contain lists for grids and matrices. Beware of shared‑row pitfalls when multiplying lists.

# Correct way to build a 3×3 zero matrix
m = [[0 for _ in range(3)] for _ in range(3)]

# WRONG: rows share the same inner list (aliasing)
wrong = [[0]*3]*3
wrong[0][0] = 1
print(wrong)  # [[1, 0, 0], [1, 0, 0], [1, 0, 0]]  <– all rows changed!

# Accessing and updating
m[1][2] = 7

# Transpose
mt = [list(col) for col in zip(*m)]

  • Use a comprehension to create independent rows; avoid list multiplication for nested structures.
  • For large matrices and numeric work, consider numpy arrays; lists are general‑purpose, not optimized for vector math.

9.Best Practices and Performance Notes

  • Use append or extend inside loops; avoid repeated concatenation like lst = lst + [x] (creates new lists repeatedly).
  • To build large lists efficiently, prefer comprehensions or generator expressions feeding into list().
  • When storing many booleans or numeric arrays, consider specialized types (array, numpy) for memory/performance.
  • Avoid mutating a list while iterating over it; iterate over a copy (lst[:]) or build a new list.
  • Use collections.deque for queue/stack use‑cases requiring fast pops from the left.

# Avoid modifying while iterating
lst = [1, 2, 3, 4]
for x in lst[:]:           # iterate over a copy
    if x % 2 == 0:
        lst.remove(x)
# lst -> [1, 3]

10. Practice Exercises (Optional)

  1. Given a list of words, build a new list of unique lowercase words sorted by length, then alphabetically.
  2. Write a function that flattens a nested list of integers of arbitrary depth.
  3. From a list of dicts with keys name and score, return the top 3 names by score (stable for ties).
Scroll to Top
Tutorialsjet.com