Registry Synced

Week 7: Tuples, Sets & Dictionaries

4267 words
21 min read
2026-09-12

Reading compass

Now · TL;DR

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:
python
list
tuple
string
Week 7 extends the collection idea to structures where lookup and membership matter more than position:
python
dictionary
set
Core mental models:
List:index→value\boxed{ \text{List}: index\rightarrow value } Dictionary:key→value\boxed{ \text{Dictionary}: key\rightarrow value } Set:collection of unique values\boxed{ \text{Set}: collection\ of\ unique\ values }
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:
python
student = {
    "name": "Asha",
    "marks": 82,
    "city": "Chennai"
}
Conceptually:
text
"name"  → "Asha"
"marks" → 82
"city"  → "Chennai"

2. Key-value model

A dictionary can be viewed as:
key→value\boxed{ key\rightarrow value }
For example:
python
marks = {
    "A": 80,
    "B": 92,
    "C": 67
}
Then:
python
marks["B"]
gives:
text
92

3. Dictionary vs list

A list:
python
x = [10, 20, 30]
uses integer positions:
python
x[1]
A dictionary:
python
x = {"a": 10, "b": 20}
uses keys:
python
x["b"]
So the indexing idea becomes more general.

4. Creating an empty dictionary

python
d = {}
Initially:
∣d∣=0.|d|=0.
You can then insert key-value pairs.

5. Insert / assign

python
d["name"] = "Ravi"
d["marks"] = 75
Now:
python
d
contains conceptually:
text
{
    "name": "Ravi",
    "marks": 75
}

6. Updating an existing key

python
d["marks"] = 90
does not create another "marks" entry.
It replaces the previous value.
Dictionary keys are unique.

7. Unique keys

This:
python
d = {
    "x": 10,
    "x": 20
}
does not represent two independent "x" keys.
A dictionary maps each key to one current value.
Conceptually:
one key→one stored value\boxed{ \text{one key}\rightarrow\text{one stored value} }

8. Values need not be unique

This is fine:
python
d = {
    "A": 80,
    "B": 80,
    "C": 80
}
Different keys may map to the same value.

9. Membership in dictionary

python
key in d
tests whether a key exists.
Example:
python
d = {"a": 10, "b": 20}

print("a" in d)
Output:
text
True

10. Important: membership checks keys

For:
python
d = {"a": 10}
python
10 in d
is not asking whether 10 is a value.
It checks whether:
text
10
is a key.
Usually false here.

11. Safe lookup

This can fail if key is missing:
python
d["score"]
Safer approach:
python
if "score" in d:
    print(d["score"])

12. .get()

Dictionaries provide:
python
d.get(key)
If key is missing, it usually returns:
python
None
instead of raising a key lookup error.
Example:
python
d = {"a": 5}

print(d.get("b"))
Output:
text
None

13. Default with .get()

python
d.get(key, default)
Example:
python
count = d.get("apple", 0)
If "apple" is absent:
count=0.count=0.
This is extremely useful for frequency counting.

14. Frequency dictionary

Suppose:
python
values = [2, 1, 2, 3, 2, 1]
We want:
text
1 → 2 times
2 → 3 times
3 → 1 time
Use:
python
freq = {}

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:
python
freq = {}

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:
python
count_1
count_2
count_3
...
A dictionary lets the data value itself become the key:
value→count\boxed{ value\rightarrow count }
This generalizes naturally.

18. Iterating through dictionary keys

python
for key in d:
    print(key)
By default, iteration is over keys.
Example:
python
d = {"a": 10, "b": 20}

for k in d:
    print(k)
prints the keys.

19. Iterating through values

python
for value in d.values():
    print(value)

20. Iterating through key-value pairs

python
for key, value in d.items():
    print(key, value)
This is one of the most useful dictionary patterns.

21. Example

python
marks = {
    "A": 80,
    "B": 92,
    "C": 67
}

for student, mark in marks.items():
    print(student, mark)
Conceptually visits:
text
A 80
B 92
C 67

22. Find key with maximum value

python
best_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:
text
best_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

python
len(d)
returns the number of key-value pairs.
Example:
python
d = {"a": 10, "b": 20}
Then:
len(d)=2.len(d)=2.

25. Delete a dictionary entry

python
del d[key]
Example:
python
d = {"a": 10, "b": 20}

del d["a"]
Result:
python
{"b": 20}

26. .pop()

python
value = d.pop(key)
removes the key and returns its value.
Example:
python
d = {"a": 10, "b": 20}

x = d.pop("a")
Then:
text
x = 10
d = {"b": 20}

27. Dictionary values can be collections

Example:
python
students = {
    "A": [80, 90, 75],
    "B": [70, 65, 88]
}
Then:
python
students["A"]
returns:
text
[80, 90, 75]

28. Nested dictionary

python
students = {
    "A": {
        "marks": 80,
        "city": "Delhi"
    },
    "B": {
        "marks": 90,
        "city": "Mumbai"
    }
}
Then:
python
students["A"]["marks"]
returns:
text
80

29. Nested access

Read:
python
students["A"]["marks"]
step-by-step:
  1. students["A"]
  2. obtain A's inner dictionary
  3. look up "marks" inside that dictionary
This is the same nested-indexing logic seen with lists.

30. Dictionary as a lookup table

Suppose:
python
capital = {
    "India": "New Delhi",
    "Japan": "Tokyo",
    "France": "Paris"
}
Then:
python
capital["Japan"]
gives:
text
Tokyo
This is a direct mapping problem.

31. Dictionary as a finite function

Mathematically, a dictionary behaves somewhat like a finite mapping:
f:key↦value.f:key\mapsto value.
For example:
f("Japan")="Tokyo".f(\text{"Japan"})=\text{"Tokyo"}.
This connects Python dictionaries to mathematical function/mapping intuition.

32. Grouping values

Suppose:
python
records = [
    ("A", 10),
    ("B", 20),
    ("A", 15)
]
We may want totals:
text
A → 25
B → 20
Algorithm:
python
total = {}

for key, value in records:
    total[key] = total.get(key, 0) + value

33. Grouped sum pattern

The reusable pattern is:
python
sum_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

python
count_by_group = {}

for group in data:
    count_by_group[group] = count_by_group.get(group, 0) + 1

35. Grouped average

Maintain both:
python
total = {}
count = {}
For each observation:
python
total[group] = total.get(group, 0) + value
count[group] = count.get(group, 0) + 1
Then:
average[group]=total[group]count[group].average[group] = \frac{total[group]}{count[group]}.
Suppose:
python
names = ["A", "B", "C"]
marks = [80, 90, 70]
Conceptually build:
python
{
    "A": 80,
    "B": 90,
    "C": 70
}
using indexes:
python
d = {}

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:
python
names[i]
corresponds to:
python
marks[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:
python
s = {1, 2, 3}
The key properties:
  • no duplicate elements
  • membership-oriented
  • no positional indexing like a list

39. Duplicates disappear

python
s = {1, 2, 2, 3, 3, 3}
represents conceptually:
text
{1, 2, 3}
Each distinct value appears once.

40. Set from list

python
values = [1, 2, 2, 3, 1]

unique = set(values)
Result contains:
text
1, 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:
python
s = set()

42. Membership

python
x in s
checks whether a value is in the set.
Example:
python
s = {2, 4, 6}

print(4 in s)
Output:
text
True

43. Add element

python
s.add(x)
Example:
python
s = {1, 2}
s.add(3)
Result:
text
{1, 2, 3}

44. Adding duplicate

python
s = {1, 2}
s.add(2)
Set remains conceptually:
text
{1, 2}
No second copy is created.

45. Remove from set

python
s.remove(x)
removes an element.
If the element is absent, this can raise an error.

46. discard()

python
s.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

python
for x in s:
    print(x)
You can iterate over set elements.
But do not rely on positional indexing:
python
s[0]
is not the normal set model.

48. Sets are not positional sequences

List:
python
x[0]
makes sense.
Set:
python
s[0]
does not.
A set answers:
Is this value present?
rather than:
What value is stored at position 0?

49. Union

For sets AA and BB:
A∪BA\cup B
contains elements appearing in either set.
Python:
python
A | B
or:
python
A.union(B)

50. Example union

python
A = {1, 2, 3}
B = {3, 4, 5}
Then:
A∪B={1,2,3,4,5}.A\cup B = \{1,2,3,4,5\}.

51. Intersection

Elements common to both:
A∩B.A\cap B.
Python:
python
A & B
or:
python
A.intersection(B)
Example:
{1,2,3}∩{3,4,5}={3}.\{1,2,3\}\cap\{3,4,5\} = \{3\}.

52. Difference

Elements in A but not B:
A−B.A-B.
Python:
python
A - B
Example:
{1,2,3}−{3,4}={1,2}.\{1,2,3\}-\{3,4\} = \{1,2\}.

53. Difference is directional

In general:
A−B≠B−A.A-B\neq B-A.
Example:
A={1,2,3}A=\{1,2,3\} B={3,4}.B=\{3,4\}.
Then:
A−B={1,2}A-B=\{1,2\}
but:
B−A={4}.B-A=\{4\}.

54. Symmetric difference

Elements in exactly one of the two sets:
A△B.A\triangle B.
Python:
python
A ^ B
Example:
{1,2,3}△{3,4}={1,2,4}.\{1,2,3\}\triangle\{3,4\} = \{1,2,4\}.

55. Subset

Python:
python
A <= B
can test whether:
A⊆B.A\subseteq B.
Example:
python
{1, 2} <= {1, 2, 3}
is true.

56. Proper subset

Python:
python
A < B
can test proper-subset relation.
Conceptually:
A⊂BA\subset B
with:
A≠B.A\neq B.

57. Superset

python
A >= B
tests whether A contains every element of B.

58. Set equality

python
{1, 2, 3} == {3, 2, 1}
is:
text
True
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

PropertyListSet
Ordered sequenceYesNot positional
DuplicatesAllowedRemoved
IndexingYesNo
MembershipYesYes
Useful forsequencesuniqueness/membership

60. Remove duplicates

Given:
python
values = [3, 1, 3, 2, 1]
quick deduplication:
python
unique = 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

python
seen = 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

python
seen = 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

python
len(set(values))
gives the number of distinct elements.
Example:
python
values = [1, 2, 2, 3, 3]
Then:
∣{1,2,3}∣=3.|\{1,2,3\}|=3.

65. Dictionary keys behave set-like

Dictionary keys must be unique.
For:
python
d = {
    "a": 10,
    "b": 20
}
the keys are conceptually:
text
{"a", "b"}
This is why membership:
python
"a" in d
tests keys.

66. .keys()

python
d.keys()
provides a view of dictionary keys.
Example:
python
for k in d.keys():
    print(k)
Though:
python
for k in d:
is usually simpler.

67. .values()

python
d.values()
provides the stored values.
Useful when keys do not matter to the current computation.

68. .items()

python
d.items()
provides key-value pairs.
Each pair can be unpacked:
python
for key, value in d.items():

69. Tuple connection

Each dictionary item behaves conceptually like a pair:
python
(key, value)
So:
python
for key, value in d.items():
uses tuple-style unpacking.
This connects dictionaries to Week 6 tuples.

70. Dictionary comprehension

Python provides concise dictionary construction:
python
squares = {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:
python
result = {}

for x in range(5):
    result[x] = x ** 2
Use the expanded form for tracing.

72. Set comprehension

python
squares = {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:
python
courses = {
    "Maths": {"A", "B", "C"},
    "Python": {"B", "C", "D"}
}
Now:
python
courses["Maths"] & courses["Python"]
gives students enrolled in both:
text
{"B", "C"}
This combines dictionaries and sets.

75. Real data pattern

Suppose:
python
student_marks = {
    "A": [80, 90, 85],
    "B": [50, 60, 55]
}
You can iterate:
python
for 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:
python
temps = {
    "Mon": 30,
    "Tue": 32,
    "Wed": 28
}
Build Fahrenheit mapping:
python
fahrenheit = {}

for day, c in temps.items():
    fahrenheit[day] = 9 / 5 * c + 32
Keys stay same; values transform.

77. Filter dictionary entries

python
high_marks = {}

for name, mark in marks.items():
    if mark >= 80:
        high_marks[name] = mark
This is dictionary filtering.

78. Reverse mapping warning

Suppose:
python
d = {
    "A": 80,
    "B": 80
}
A naive reversed dictionary:
python
reverse[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:
text
A → 80
B → 80
This is many keys mapping to one value.
Reversing would require:
text
80 → {A, B}
not simply:
text
80 → one student
This is a useful structural insight.

80. Group values into lists

A general pattern:
python
groups = {}

for key, value in data:
    if key not in groups:
        groups[key] = []

    groups[key].append(value)
Result:
text
key → 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:
avoid structurally changing the collection you are traversing\boxed{ \text{avoid structurally changing the collection you are traversing} }

83. Same principle for sets

Changing set size while directly iterating over it can also be problematic.
Prefer:
python
result = set()

for x in original:
    ...
when constructing a transformed set.

Common mistake: dictionary lookup by value
Given:
python
d = {"A": 80}
this:
python
d[80]
does not retrieve "A".
Dictionary access is:
text
key → value
not automatically:
text
value → 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:
1.1.
Common mistake: use
{} for empty set
Wrong:
python
s = {}
This creates a dictionary.
Correct:
python
s = set()

Common mistake: set indexing
Wrong:
python
s[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
python
x in d
checks keys.
To inspect values:
python
x in d.values()

Common mistake: missing key initialization
Wrong frequency code:
python
freq[x] += 1
when x has never appeared.
Correct:
python
freq[x] = freq.get(x, 0) + 1
or explicit initialization.

Common mistake: overwrite instead of accumulate
Suppose grouped sum.
Wrong:
python
total[group] = value
on every occurrence.
This keeps only the latest value.
Correct:
python
total[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:
python
seen = 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

python
d = {}

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

python
x = ["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

python
seen = set()
count = 0

for x in [2, 3, 2, 4, 3]:
    if x not in seen:
        seen.add(x)
        count += 1
Trace first appearances:
text
2 → new
3 → new
2 → already seen
4 → new
3 → already seen
Final:
count=3.count=3.

98. Frequency vs set

For:
python
[2, 3, 2, 4, 3]
Set gives:
text
which distinct values exist?
{2,3,4}\{2,3,4\}
Dictionary frequency gives:
text
how 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 ii?

Tuple

What fixed ordered values belong together?

Dictionary

What value belongs to key kk?

Set

Is value xx 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:
text
list:
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:
text
READ 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:
ordered collections\boxed{ \text{ordered collections} }
such as lists and strings.
Week 7 adds:
associations + uniqueness\boxed{ \text{associations + uniqueness} }
through dictionaries and sets.
Conceptually:
text
LIST
index → value

DICTIONARY
key → value

SET
unique values / membership

103. Compact dictionary cheat sheet

python
d = {}

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:
python
freq[x] = freq.get(x, 0) + 1

104. Compact set cheat sheet

python
s = 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

python
freq = {}

for x in values:
    freq[x] = freq.get(x, 0) + 1

Grouped sum

python
total = {}

for group, value in data:
    total[group] = total.get(group, 0) + value

Group into lists

python
groups = {}

for key, value in data:
    if key not in groups:
        groups[key] = []

    groups[key].append(value)

Unique values

python
unique = set(values)

Detect duplicates

python
seen = 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:
  1. Explain the dictionary key-value model.
  2. Create and update dictionaries.
  3. Distinguish keys from values.
  4. Test key membership.
  5. Use .get() safely.
  6. Iterate through keys, values, and items.
  7. Construct frequency dictionaries.
  8. Build grouped sums and counts.
  9. Store lists or dictionaries as dictionary values.
  10. Understand nested dictionary access.
  11. Explain what a set represents.
  12. Create empty and non-empty sets.
  13. Use set membership.
  14. Add/remove set elements.
  15. Understand duplicate elimination.
  16. Compute union, intersection, difference, and symmetric difference.
  17. Understand subset/superset relations.
  18. Use sets to track seen values.
  19. Detect duplicates.
  20. Count distinct values.
  21. Distinguish list, tuple, dictionary, set, and string roles.
  22. 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
Document outline

Keep your place and jump directly to a heading.

Table of contents

No note selected

Open a chapter to see its outline, backlinks, and sources here.