Week 7: Tuples, Sets & Dictionaries
4267 words
21 min read
2026-09-12T00:00:00.000Z
Visual companion
Python
Type and operator map
Python Week 1: the first filter for runtime behavior
View
Revision summary
What this note is really saying
Short form
Immutable tuples, sets and set algebra, dictionary key-value mappings, hashing requirements, and dict methods. # Programming in Python — Week 7: Tuples, Sets & Dictionaries The official IITM syllabus lists **Week 7: Basic Collections in Python (Continued)**.

Visual strip
Relevant recall pieces for this note
Programming in Python — Week 7: Tuples, Sets & Dictionaries
The official IITM syllabus lists Week 7: Basic Collections in Python (Continued). It does not give a finer breakdown, so the detailed material below is a standard continuation of Python collections, not a claim about the exact lecture ordering.
TL;DR
Week 6 focused mainly on ordered sequences:
pythonlist tuple string
Week 7 extends the collection idea to structures where lookup and membership matter more than position:
pythondictionary set
Core mental models:
These structures are useful for:
- frequencies
- lookup tables
- grouping
- counting
- membership tests
- removing duplicates
- mapping identifiers to data
- comparing groups of values
1. Dictionary
A dictionary stores associations between keys and values.
Example:
pythonstudent = { "name": "Asha", "marks": 82, "city": "Chennai" }
Conceptually:
text"name" → "Asha" "marks" → 82 "city" → "Chennai"
2. Key-value model
A dictionary can be viewed as:
For example:
pythonmarks = { "A": 80, "B": 92, "C": 67 }
Then:
pythonmarks["B"]
gives:
text92
3. Dictionary vs list
A list:
pythonx = [10, 20, 30]
uses integer positions:
pythonx[1]
A dictionary:
pythonx = {"a": 10, "b": 20}
uses keys:
pythonx["b"]
So the indexing idea becomes more general.
4. Creating an empty dictionary
pythond = {}
Initially:
You can then insert key-value pairs.
5. Insert / assign
pythond["name"] = "Ravi" d["marks"] = 75
Now:
pythond
contains conceptually:
text{ "name": "Ravi", "marks": 75 }
6. Updating an existing key
pythond["marks"] = 90
does not create another
"marks" entry.It replaces the previous value.
Dictionary keys are unique.
7. Unique keys
This:
pythond = { "x": 10, "x": 20 }
does not represent two independent
"x" keys.A dictionary maps each key to one current value.
Conceptually:
8. Values need not be unique
This is fine:
pythond = { "A": 80, "B": 80, "C": 80 }
Different keys may map to the same value.
9. Membership in dictionary
pythonkey in d
tests whether a key exists.
Example:
pythond = {"a": 10, "b": 20} print("a" in d)
Output:
textTrue
10. Important: membership checks keys
For:
pythond = {"a": 10}
python10 in d
is not asking whether 10 is a value.
It checks whether:
text10
is a key.
Usually false here.
11. Safe lookup
This can fail if key is missing:
pythond["score"]
Safer approach:
pythonif "score" in d: print(d["score"])
12. .get()
Dictionaries provide:
pythond.get(key)
If key is missing, it usually returns:
pythonNone
instead of raising a key lookup error.
Example:
pythond = {"a": 5} print(d.get("b"))
Output:
textNone
13. Default with .get()
pythond.get(key, default)
Example:
pythoncount = d.get("apple", 0)
If
"apple" is absent:This is extremely useful for frequency counting.
14. Frequency dictionary
Suppose:
pythonvalues = [2, 1, 2, 3, 2, 1]
We want:
text1 → 2 times 2 → 3 times 3 → 1 time
Use:
pythonfreq = {} for x in values: if x in freq: freq[x] += 1 else: freq[x] = 1
Result:
python{ 2: 3, 1: 2, 3: 1 }
15. Frequency pattern with .get()
Shorter:
pythonfreq = {} for x in values: freq[x] = freq.get(x, 0) + 1
Interpretation:
previous count, or 0 if absent, then add 1.
16. Trace frequency counting
Input:
python[2, 1, 2, 2]
Start:
text{}
Read 2:
text{2: 1}
Read 1:
text{2: 1, 1: 1}
Read 2:
text{2: 2, 1: 1}
Read 2:
text{2: 3, 1: 1}
17. Why dictionaries fit frequency problems
Without a dictionary, you might need separate variables:
pythoncount_1 count_2 count_3 ...
A dictionary lets the data value itself become the key:
This generalizes naturally.
18. Iterating through dictionary keys
pythonfor key in d: print(key)
By default, iteration is over keys.
Example:
pythond = {"a": 10, "b": 20} for k in d: print(k)
prints the keys.
19. Iterating through values
pythonfor value in d.values(): print(value)
20. Iterating through key-value pairs
pythonfor key, value in d.items(): print(key, value)
This is one of the most useful dictionary patterns.
21. Example
pythonmarks = { "A": 80, "B": 92, "C": 67 } for student, mark in marks.items(): print(student, mark)
Conceptually visits:
textA 80 B 92 C 67
22. Find key with maximum value
pythonbest_student = None best_mark = None for student, mark in marks.items(): if best_mark is None or mark > best_mark: best_mark = mark best_student = student
At the end:
textbest_student
stores the key associated with the largest value.
23. Cleaner initialization when non-empty
If dictionary is guaranteed non-empty, another strategy is to initialize from one actual entry rather than inventing artificial values.
The core CT principle remains:
initialize from real data when possible.
24. Dictionary length
pythonlen(d)
returns the number of key-value pairs.
Example:
pythond = {"a": 10, "b": 20}
Then:
25. Delete a dictionary entry
pythondel d[key]
Example:
pythond = {"a": 10, "b": 20} del d["a"]
Result:
python{"b": 20}
26. .pop()
pythonvalue = d.pop(key)
removes the key and returns its value.
Example:
pythond = {"a": 10, "b": 20} x = d.pop("a")
Then:
textx = 10 d = {"b": 20}
27. Dictionary values can be collections
Example:
pythonstudents = { "A": [80, 90, 75], "B": [70, 65, 88] }
Then:
pythonstudents["A"]
returns:
text[80, 90, 75]
28. Nested dictionary
pythonstudents = { "A": { "marks": 80, "city": "Delhi" }, "B": { "marks": 90, "city": "Mumbai" } }
Then:
pythonstudents["A"]["marks"]
returns:
text80
29. Nested access
Read:
pythonstudents["A"]["marks"]
step-by-step:
students["A"]- obtain A's inner dictionary
- look up
"marks"inside that dictionary
This is the same nested-indexing logic seen with lists.
30. Dictionary as a lookup table
Suppose:
pythoncapital = { "India": "New Delhi", "Japan": "Tokyo", "France": "Paris" }
Then:
pythoncapital["Japan"]
gives:
textTokyo
This is a direct mapping problem.
31. Dictionary as a finite function
Mathematically, a dictionary behaves somewhat like a finite mapping:
For example:
This connects Python dictionaries to mathematical function/mapping intuition.
32. Grouping values
Suppose:
pythonrecords = [ ("A", 10), ("B", 20), ("A", 15) ]
We may want totals:
textA → 25 B → 20
Algorithm:
pythontotal = {} for key, value in records: total[key] = total.get(key, 0) + value
33. Grouped sum pattern
The reusable pattern is:
pythonsum_by_group = {} for group, value in data: sum_by_group[group] = sum_by_group.get(group, 0) + value
This appears constantly in data processing.
34. Grouped count pattern
pythoncount_by_group = {} for group in data: count_by_group[group] = count_by_group.get(group, 0) + 1
35. Grouped average
Maintain both:
pythontotal = {} count = {}
For each observation:
pythontotal[group] = total.get(group, 0) + value count[group] = count.get(group, 0) + 1
Then:
36. Dictionary from two related lists
Suppose:
pythonnames = ["A", "B", "C"] marks = [80, 90, 70]
Conceptually build:
python{ "A": 80, "B": 90, "C": 70 }
using indexes:
pythond = {} for i in range(len(names)): d[names[i]] = marks[i]
37. Parallel lists caveat
When using two lists as paired data, they must remain aligned.
If:
pythonnames[i]
corresponds to:
pythonmarks[i]
then mismatched lengths/order can corrupt the relationship.
A dictionary or list of records often expresses such relationships more directly.
38. Set
A Python set stores unique elements.
Example:
pythons = {1, 2, 3}
The key properties:
- no duplicate elements
- membership-oriented
- no positional indexing like a list
39. Duplicates disappear
pythons = {1, 2, 2, 3, 3, 3}
represents conceptually:
text{1, 2, 3}
Each distinct value appears once.
40. Set from list
pythonvalues = [1, 2, 2, 3, 1] unique = set(values)
Result contains:
text1, 2, 3
This is a convenient deduplication pattern.
41. Empty set
Important:
python{}
creates an empty dictionary, not an empty set.
To create an empty set:
pythons = set()
42. Membership
pythonx in s
checks whether a value is in the set.
Example:
pythons = {2, 4, 6} print(4 in s)
Output:
textTrue
43. Add element
pythons.add(x)
Example:
pythons = {1, 2} s.add(3)
Result:
text{1, 2, 3}
44. Adding duplicate
pythons = {1, 2} s.add(2)
Set remains conceptually:
text{1, 2}
No second copy is created.
45. Remove from set
pythons.remove(x)
removes an element.
If the element is absent, this can raise an error.
46. discard()
pythons.discard(x)
removes
x if present but does not raise the same missing-element error behavior as remove().Useful when absence is acceptable.
47. Set iteration
pythonfor x in s: print(x)
You can iterate over set elements.
But do not rely on positional indexing:
pythons[0]
is not the normal set model.
48. Sets are not positional sequences
List:
pythonx[0]
makes sense.
Set:
pythons[0]
does not.
A set answers:
Is this value present?
rather than:
What value is stored at position 0?
49. Union
For sets A and B:
contains elements appearing in either set.
Python:
pythonA | B
or:
pythonA.union(B)
50. Example union
pythonA = {1, 2, 3} B = {3, 4, 5}
Then:
51. Intersection
Elements common to both:
Python:
pythonA & B
or:
pythonA.intersection(B)
Example:
52. Difference
Elements in A but not B:
Python:
pythonA - B
Example:
53. Difference is directional
In general:
Example:
Then:
but:
54. Symmetric difference
Elements in exactly one of the two sets:
Python:
pythonA ^ B
Example:
55. Subset
Python:
pythonA <= B
can test whether:
Example:
python{1, 2} <= {1, 2, 3}
is true.
56. Proper subset
Python:
pythonA < B
can test proper-subset relation.
Conceptually:
with:
57. Superset
pythonA >= B
tests whether A contains every element of B.
58. Set equality
python{1, 2, 3} == {3, 2, 1}
is:
textTrue
because order is irrelevant to mathematical set equality.
Contrast with lists:
python[1, 2, 3] == [3, 2, 1]
which is false.
59. List vs set
| Property | List | Set |
|---|---|---|
| Ordered sequence | Yes | Not positional |
| Duplicates | Allowed | Removed |
| Indexing | Yes | No |
| Membership | Yes | Yes |
| Useful for | sequences | uniqueness/membership |
60. Remove duplicates
Given:
pythonvalues = [3, 1, 3, 2, 1]
quick deduplication:
pythonunique = set(values)
But if exact original order must be preserved, converting directly to a set is not the right conceptual tool.
61. Order-preserving deduplication pattern
pythonseen = set() result = [] for x in values: if x not in seen: seen.add(x) result.append(x)
For:
python[3, 1, 3, 2, 1]
result:
python[3, 1, 2]
62. Why use both set and list?
The set answers efficiently:
Have I seen this value before?
The list preserves:
In what order did first appearances occur?
Different collections can cooperate in one algorithm.
63. Detect duplicate
pythonseen = set() duplicate_found = False for x in values: if x in seen: duplicate_found = True break seen.add(x)
This is a classic set-based search pattern.
64. Count distinct values
pythonlen(set(values))
gives the number of distinct elements.
Example:
pythonvalues = [1, 2, 2, 3, 3]
Then:
65. Dictionary keys behave set-like
Dictionary keys must be unique.
For:
pythond = { "a": 10, "b": 20 }
the keys are conceptually:
text{"a", "b"}
This is why membership:
python"a" in d
tests keys.
66. .keys()
pythond.keys()
provides a view of dictionary keys.
Example:
pythonfor k in d.keys(): print(k)
Though:
pythonfor k in d:
is usually simpler.
67. .values()
pythond.values()
provides the stored values.
Useful when keys do not matter to the current computation.
68. .items()
pythond.items()
provides key-value pairs.
Each pair can be unpacked:
pythonfor key, value in d.items():
69. Tuple connection
Each dictionary item behaves conceptually like a pair:
python(key, value)
So:
pythonfor key, value in d.items():
uses tuple-style unpacking.
This connects dictionaries to Week 6 tuples.
70. Dictionary comprehension
Python provides concise dictionary construction:
pythonsquares = {x: x ** 2 for x in range(5)}
Result:
python{ 0: 0, 1: 1, 2: 4, 3: 9, 4: 16 }
71. Expand comprehension mentally
python{x: x ** 2 for x in range(5)}
means conceptually:
pythonresult = {} for x in range(5): result[x] = x ** 2
Use the expanded form for tracing.
72. Set comprehension
pythonsquares = {x ** 2 for x in range(5)}
This creates a set, because each generated expression is a single element rather than
key: value.73. Dict vs set literal
Dictionary:
python{"a": 1, "b": 2}
contains colons.
Set:
python{"a", "b"}
contains elements only.
Empty
{} remains a dictionary.74. Collections can be nested
Example:
pythoncourses = { "Maths": {"A", "B", "C"}, "Python": {"B", "C", "D"} }
Now:
pythoncourses["Maths"] & courses["Python"]
gives students enrolled in both:
text{"B", "C"}
This combines dictionaries and sets.
75. Real data pattern
Suppose:
pythonstudent_marks = { "A": [80, 90, 85], "B": [50, 60, 55] }
You can iterate:
pythonfor student, marks in student_marks.items(): avg = sum(marks) / len(marks) print(student, avg)
This combines:
- dictionary
- list
- loop
- aggregation
76. Transformation dictionary
Suppose Celsius temperatures:
pythontemps = { "Mon": 30, "Tue": 32, "Wed": 28 }
Build Fahrenheit mapping:
pythonfahrenheit = {} for day, c in temps.items(): fahrenheit[day] = 9 / 5 * c + 32
Keys stay same; values transform.
77. Filter dictionary entries
pythonhigh_marks = {} for name, mark in marks.items(): if mark >= 80: high_marks[name] = mark
This is dictionary filtering.
78. Reverse mapping warning
Suppose:
pythond = { "A": 80, "B": 80 }
A naive reversed dictionary:
pythonreverse[80] = "A" reverse[80] = "B"
loses one association because dictionary keys must be unique.
So reversing a mapping is not always one-to-one.
79. One-to-one vs many-to-one
Original dictionary can have:
textA → 80 B → 80
This is many keys mapping to one value.
Reversing would require:
text80 → {A, B}
not simply:
text80 → one student
This is a useful structural insight.
80. Group values into lists
A general pattern:
pythongroups = {} for key, value in data: if key not in groups: groups[key] = [] groups[key].append(value)
Result:
textkey → list of associated values
81. Example
Input:
python[ ("A", 10), ("B", 7), ("A", 12) ]
Grouped:
python{ "A": [10, 12], "B": [7] }
82. Dictionary mutation while iterating
Be cautious about adding/removing dictionary keys while iterating directly over the same dictionary.
It can cause runtime problems or confusing behavior.
A safer strategy may be:
- build another dictionary
- or iterate over a separate snapshot when required
General principle:
83. Same principle for sets
Changing set size while directly iterating over it can also be problematic.
Prefer:
pythonresult = set() for x in original: ...
when constructing a transformed set.
Common mistake: dictionary lookup by value
Given:
pythond = {"A": 80}
this:
pythond[80]
does not retrieve
"A".Dictionary access is:
textkey → value
not automatically:
textvalue → key
Common mistake: assuming dictionary keys can duplicate
They cannot represent multiple independent entries with the same key.
Later assignment replaces the previous value.
Common mistake: assuming set keeps duplicates
python{1, 1, 1}
contains one distinct value.
Set cardinality:
Common mistake: use
{} for empty setWrong:
pythons = {}
This creates a dictionary.
Correct:
pythons = set()
Common mistake: set indexing
Wrong:
pythons[0]
Sets are not positional sequences.
Use membership/iteration instead.
Common mistake: set order assumptions
Do not write algorithms whose correctness depends on arbitrary set traversal order.
If order is semantically important, use an ordered structure such as a list.
Common mistake: dictionary membership checks values
pythonx in d
checks keys.
To inspect values:
pythonx in d.values()
Common mistake: missing key initialization
Wrong frequency code:
pythonfreq[x] += 1
when
x has never appeared.Correct:
pythonfreq[x] = freq.get(x, 0) + 1
or explicit initialization.
Common mistake: overwrite instead of accumulate
Suppose grouped sum.
Wrong:
pythontotal[group] = value
on every occurrence.
This keeps only the latest value.
Correct:
pythontotal[group] = total.get(group, 0) + value
Common mistake: list where set is conceptually better
To ask repeatedly:
Have I seen this element?
a set expresses the concept directly:
pythonseen = set()
rather than maintaining a list just for uniqueness.
Choosing an appropriate data structure makes algorithms clearer.
Common mistake: set where list is needed
If you need:
- duplicates
- positional indexing
- meaningful sequence order
then a set loses information.
Collection choice depends on the problem.
95. Trace dictionary mutation
pythond = {} d["a"] = 1 d["b"] = 2 d["a"] += 4 print(d)
Trace:
text{} ↓ {"a": 1} ↓ {"a": 1, "b": 2} ↓ {"a": 5, "b": 2}
96. Trace frequency algorithm
pythonx = ["a", "b", "a", "c", "b", "a"] freq = {} for item in x: freq[item] = freq.get(item, 0) + 1
Final:
python{ "a": 3, "b": 2, "c": 1 }
97. Trace set algorithm
pythonseen = set() count = 0 for x in [2, 3, 2, 4, 3]: if x not in seen: seen.add(x) count += 1
Trace first appearances:
text2 → new 3 → new 2 → already seen 4 → new 3 → already seen
Final:
98. Frequency vs set
For:
python[2, 3, 2, 4, 3]
Set gives:
{2,3,4}textwhich distinct values exist?
Dictionary frequency gives:
texthow many times does each occur?
python{ 2: 2, 3: 2, 4: 1 }
Different questions → different structures.
99. Choosing a collection
Ask what relationship your data naturally has.
List
What is at position i?
Tuple
What fixed ordered values belong together?
Dictionary
What value belongs to key k?
Set
Is value x present / which unique values exist?
String
What sequence of characters do I have?
100. Complexity intuition
For lists, finding a target may require scanning many entries.
Sets and dictionaries are designed around efficient membership/key lookup.
At this level, the important conceptual distinction is:
textlist: search through sequence dict/set: lookup/membership-oriented structure
Exact implementation complexity can be studied later.
101. Collection-processing toolbox
By now, many algorithms can be described as:
textREAD DATA ↓ STORE COLLECTION ↓ ITERATE ↓ FILTER / TRANSFORM ↓ COUNT / GROUP / AGGREGATE ↓ OUTPUT
This is essentially the foundation of later data-processing work.
102. Week 6 → Week 7 progression
Week 6 emphasized:
such as lists and strings.
Week 7 adds:
through dictionaries and sets.
Conceptually:
textLIST index → value DICTIONARY key → value SET unique values / membership
103. Compact dictionary cheat sheet
pythond = {} d[key] = value d[key] key in d d.get(key) d.get(key, default) del d[key] d.pop(key) len(d) for key in d: ... for value in d.values(): ... for key, value in d.items(): ...
Frequency:
pythonfreq[x] = freq.get(x, 0) + 1
104. Compact set cheat sheet
pythons = set() s.add(x) s.remove(x) s.discard(x) x in s len(s) A | B # union A & B # intersection A - B # difference A ^ B # symmetric difference A <= B # subset A >= B # superset
105. Core Week 7 patterns
Frequency
pythonfreq = {} for x in values: freq[x] = freq.get(x, 0) + 1
Grouped sum
pythontotal = {} for group, value in data: total[group] = total.get(group, 0) + value
Group into lists
pythongroups = {} for key, value in data: if key not in groups: groups[key] = [] groups[key].append(value)
Unique values
pythonunique = set(values)
Detect duplicates
pythonseen = set() for x in values: if x in seen: ... seen.add(x)
106. What you should actually master
By the end of Python Week 7, you should be able to:
- Explain the dictionary key-value model.
- Create and update dictionaries.
- Distinguish keys from values.
- Test key membership.
- Use
.get()safely. - Iterate through keys, values, and items.
- Construct frequency dictionaries.
- Build grouped sums and counts.
- Store lists or dictionaries as dictionary values.
- Understand nested dictionary access.
- Explain what a set represents.
- Create empty and non-empty sets.
- Use set membership.
- Add/remove set elements.
- Understand duplicate elimination.
- Compute union, intersection, difference, and symmetric difference.
- Understand subset/superset relations.
- Use sets to track
seenvalues. - Detect duplicates.
- Count distinct values.
- Distinguish list, tuple, dictionary, set, and string roles.
- Choose a collection based on the problem's data relationship.
If these are comfortable, Programming in Python Week 7 is under control.
Quick Recall & Flashcards
Test your active recall before proceeding to practice problems. Format:
Question :: Answer.- Week 7 Diagnostic: Can a list be used as a key in a Python dictionary? :: Answer: B — Dictionary keys must be hashable and immutable. Lists are mutable and unhashable, raising
TypeError: unhashable type: 'list'. - Week 7 Diagnostic: What is the result of
len({1, 2, 2, 3, 3, 3})? :: Answer: 3 — Sets store only unique elements:{1, 2, 3}has length 3.
Practice & Self-Check
Attempt these diagnostic questions to verify your operational understanding.
1
Question 1
Can a list be used as a key in a Python dictionary?
MCQ
3 Unit Assessment
A. Yes, any Python object can be a dict key
B. No, dictionary keys must be hashable and immutable (lists are unhashable)
C. Only if the list contains integers
D. Yes, if the list has length <= 10
2
Question 2
What is the result of
len({1, 2, 2, 3, 3, 3})?NAT
3 Unit Assessment