Lists: indexing, slicing, methods
A list is an ordered, changeable (mutable) collection: ["a", "b", "c"]. It can hold any types, mixed, and it remembers the order you put things in.
Indexing reaches one item by position, starting at 0: tasks[0] is the first. Negative indexes count from the end: tasks[-1] is the last. An index that doesn't exist raises IndexError.
Slicing takes a sub-list with list[start:stop] — stop is *excluded*. tasks[:2] is the first two, tasks[1:] is everything from index 1 on, tasks[:] is a full copy.
The everyday methods:
.append(x)— addxto the end..insert(i, x)— putxat positioni..pop(i)— remove *and return* the item ati(default: the last)..remove(x)— delete the first item equal tox(errors if absent).x in list—Trueifxis present.
Lists are mutable: methods like .append change the list in place. And a list variable is a *reference* — b = a makes b point at the same list, so editing one shows up in the other. Use a[:] or list(a) for an independent copy.
Syntax
items = ["a", "b", "c"]
items[0] # 'a' (first)
items[-1] # 'c' (last)
items[1:] # ['b', 'c'] (slice; stop excluded)
items[:2] # ['a', 'b']
items.append("d") # add to end
items.insert(0, "z")# add at position
items.pop(0) # remove + return index 0
items.remove("b") # delete first matching value
"a" in items # membership testWorked examples
Indexing and slicing
tasks = ["deploy", "test", "review"]
print(tasks[0]) # deploy (first)
print(tasks[-1]) # review (last)
print(tasks[:2]) # ['deploy', 'test'] (first two)
print(tasks[1:]) # ['test', 'review'] (from index 1)Mutating methods + membership
queue = ["a", "b", "c"]
queue.append("d") # add to end
first = queue.pop(0) # first = "a"; removed from front
queue.remove("c") # delete by value
queue.insert(0, "x") # put "x" at the front
print(queue, first)
# Output:
# ['x', 'b', 'd'] a
print("b" in queue) # TrueA list is a reference — copy with [:] to stay independent
a = [1, 2, 3]
b = a # same list, not a copy
b.append(4)
print(a) # [1, 2, 3, 4] ← a changed too!
c = a[:] # an independent copy
c.append(5)
print(a) # [1, 2, 3, 4] ← unchanged this timeCommon mistakes & gotchas
IndexError on an out-of-range index
items[5] on a 3-item list raises IndexError: list index out of range. Indexing is 0-based, so the last valid index is len(items) - 1. Slicing, by contrast, never errors on out-of-range bounds — items[:99] just gives what's there.
.pop() returns the item, .remove() returns None
.pop(i) hands back the removed item (useful: task = queue.pop(0)). .remove(x) returns None and deletes by *value*, raising ValueError if x isn't present — guard with if x in list: first.
Assignment copies the reference, not the list
b = a makes both names point at the *same* list, so mutating through one is visible through the other. For a separate list use a[:], list(a), or a.copy().
Why it matters
Lists are the default container for "several of something" — rows from a query, lines from a file, items in a cart, results to process. The indexing/slicing/append/pop vocabulary here is among the most-typed code in all of Python, and the reference-vs-copy gotcha is behind a huge share of "why did my other variable change?" bugs.