Why four of them
C gives you one container: the array. Fixed size, one type, indexed by number. Everything else you build yourself. Python ships four, because the four answer four different questions.
| Container | Written as | Ordered | Changeable | Duplicates | Looks up by |
|---|---|---|---|---|---|
| list | [1, 2, 3] |
yes | yes | yes | position |
| tuple | (1, 2, 3) |
yes | no | yes | position |
| dict | {"a": 1} |
yes | yes | keys unique | key |
| set | {1, 2, 3} |
no | yes | no | membership |
list - the default
Use a list when you have several things of the same kind and the order matters.
marks = [72, 65, 88, 91]
marks.append(55) # add at the end
marks.insert(0, 100) # add at position 0
marks.remove(65) # remove the first 65 by value
last = marks.pop() # remove and return the last item
print(marks) # [100, 72, 88, 91]
print(len(marks)) # 4
print(marks[0], marks[-1]) # 100 91
print(marks[1:3]) # [72, 88] - from 1, up to but not including 3
marks[-1] is the last item. Negative indices count from the right. This saves you writing marks[len(marks) - 1] everywhere.
A list can hold mixed types, but if yours does, you probably want a dict or a small class instead.
b = a does not copy a list. Both names point at the same list, so changing one changes "both". Use b = a.copy() or b = a[:] when you want a real copy. This is the single most common Python bug in student code.
a = [1, 2, 3]
b = a
b.append(4)
print(a) # [1, 2, 3, 4] - a changed too
c = a.copy()
c.append(5)
print(a) # [1, 2, 3, 4] - a is safe
tuple - a list that cannot change
point = (3, 4)
x, y = point # unpacking
print(x, y) # 3 4
A tuple is fixed once created. point[0] = 9 raises TypeError. That sounds like a limitation, and it is the point: use a tuple when the number of items is part of the meaning. A 2D point always has exactly two numbers. A student record is always (roll number, name, marks).
Tuples are also the only one of these four that can be a dict key, because keys must be immutable.
A tuple of one item needs a trailing comma: (5,) is a tuple, (5) is just the number 5 in brackets.
dict - lookup by name
A dict maps a key to a value. This is the container you will use most once your programs get real.
student = {
"roll": "21CS045",
"name": "Ravi Kumar",
"cgpa": 8.2,
}
print(student["name"]) # Ravi Kumar
print(student.get("branch", "CSE")) # CSE - default if key missing
student["cgpa"] = 8.4 # update
student["branch"] = "CSE" # add
for key, value in student.items():
print(f"{key}: {value}")
student["branch"] on a missing key raises KeyError and stops the program. student.get("branch") returns None instead, and student.get("branch", "CSE") returns a default you choose. Use get when the key might genuinely be absent.
set - membership and uniqueness
a = {1, 2, 3, 4}
b = {3, 4, 5}
print(a | b) # {1, 2, 3, 4, 5} union
print(a & b) # {3, 4} intersection
print(a - b) # {1, 2} difference
nums = [1, 2, 2, 3, 3, 3]
print(set(nums)) # {1, 2, 3}
print(len(set(nums))) # 3 distinct values
An empty set is set(), not {}. {} is an empty dict.
The reason this lesson matters: speed
Checking whether an item is present is the difference between a program that finishes and one that does not.
big_list = list(range(1000000))
big_set = set(big_list)
# 999999 in big_list -> scans every element, ~1,000,000 comparisons
# 999999 in big_set -> one hash computation, ~1 comparison
in on a list is O(n). in on a set or a dict is O(1) on average, because they use a hash table. For 1,000,000 items that is the difference between milliseconds and minutes.
The rule to remember: if your program asks "have I seen this before?", use a set or a dict, never a list.
Lab assignments that ask you to "remove duplicates" or "count occurrences" are testing exactly this. set() removes duplicates in one line. collections.Counter counts them in one line. Knowing that is worth more than a 40-line loop that works.