📌 Snapshot
- Master tuples and dictionaries for CUET Python: the single element comma, unpacking and key based lookup.
- Why a tuple is locked, why a dictionary is searched by key, and what the legal keys and values can be.
- Method tables, tuple assignment and swapping, and traced programs for counting characters and number words.
- Traps NTA sets: (20) is not a tuple, KeyError versus get, duplicate keys, and sorted() on a tuple.
📖 Detailed Notes
Written and reviewed by Rohit Singh, Computer Science & Commerce faculty at UniDrill (MCA, Osmania University · 6 years teaching). Based on NCERT Computer Science Class XI, Chapter 10.
Two containers you already use without knowing it
Whenever a function returns two values, you get a tuple. Whenever you swap two variables with a, b = b, a, tuples do the work. And when you look up a friend's number in your phone, you search by name, not by position 1, 2, 3. That is how a dictionary works. This chapter finishes the family of Python data types: strings and lists you know, now the locked sequence (tuple) and the lookup table (dictionary).
What is a tuple?
A tuple is an ordered sequence of elements of any data types (integers, floats, strings, lists, even other tuples). The elements sit inside round brackets and are separated by commas. Indices start at 0, just as for strings and lists.
| Code |
|---|
tuple1 = (1, 2, 3, 4, 5) |
tuple2 = ('Economics', 87, 'Accountancy', 89.6) |
tuple3 = (10, 20, 30, [40, 50]) |
tuple4 = (1, 2, 3, 4, 5, (10, 20)) |
The last two show a tuple holding a list and a tuple holding another tuple (a nested tuple).
The single element trap. A tuple with one element needs a trailing comma. Without it, the brackets are just ordinary brackets around a number.
| Statement | Type of the value |
|---|---|
tuple5 = (20) |
int |
tuple5 = (20,) |
tuple |
seq = 1, 2, 3 |
tuple (commas alone make a tuple) |
So a sequence of comma separated values without brackets is also treated as a tuple. This is exactly why len((5)) fails with a TypeError, because (5) is the integer 5.
Pause and predict: what is type(('a')), and what is type(('a',))?
Check your answer: ('a') is just the string 'a' in brackets, so its type is str. ('a',) has the comma, so its type is tuple. The comma, not the bracket, makes the tuple.
A tuple is immutable
You can read tuple elements by index and slice them like a list, but you cannot change them. tuple1[4] = 10 raises TypeError: 'tuple' object does not support item assignment.
There is one subtlety. A tuple is locked, but if one of its elements is a mutable object such as a list, that list can still be changed. The tuple continues to hold the same list.
Worked example: the tuple that seems to change.
| Code |
|---|
tuple2 = (1, 2, 3, [8, 9]) |
tuple2[3][1] = 10 |
print(tuple2) |
| Output |
|---|
(1, 2, 3, [8, 10]) |
| Step | What happens | Allowed? |
|---|---|---|
| 1 | tuple2[3] picks the list [8, 9] |
Reading is always allowed |
| 2 | [1] = 10 changes an element of the list |
Yes, the list is mutable |
| 3 | The tuple still holds the same list object, just with new contents | The tuple itself was not changed |
By contrast, tuple2[0] = 5 would fail, because that tries to replace an element of the tuple itself.
Why use a tuple at all? A tuple is faster to iterate than a list, and data that must not change, such as the days of a week or a record, is safe in a tuple because it cannot be altered by accident. The textbook's rule of thumb: a list is typically used for items of the same type, and a tuple for items of different types.
Tuple operations
| Operation | Example | Result |
|---|---|---|
| Concatenation | (1, 3, 5) + (2, 4) |
(1, 3, 5, 2, 4) |
| Repetition (tuple first, integer second) | ('Hello', 'World') * 3 |
('Hello', 'World', 'Hello', 'World', 'Hello', 'World') |
| Repetition of one element | ("Hello",) * 4 |
('Hello', 'Hello', 'Hello', 'Hello') |
| Membership | 'Green' in ('Red', 'Green', 'Blue') |
True |
| Slicing | tuple1[2:7] |
a new tuple |
Because a tuple cannot be edited, "extending" it builds a new tuple: tuple6 = tuple6 + (6,) creates a new tuple and rebinds the name. The single element needs its comma, (6,), since tuple6 + (6) would try to add an integer to a tuple and fail.
Worked example: slicing a tuple. Let tuple1 = (10, 20, 30, 40, 50, 60, 70, 80), indices 0 to 7.
| Expression | Indices | Result |
|---|---|---|
tuple1[2:7] |
2, 3, 4, 5, 6 | (30, 40, 50, 60, 70) |
tuple1[:5] |
0 to 4 | (10, 20, 30, 40, 50) |
tuple1[2:] |
2 to the end | (30, 40, 50, 60, 70, 80) |
tuple1[0:len(tuple1):2] |
0, 2, 4, 6 | (10, 30, 50, 70) |
tuple1[-6:-4] |
2, 3 | (30, 40) |
tuple1[::-3] |
7, 4, 1 | (80, 50, 20) |
tuple1[::-1] |
7 down to 0 | (80, 70, 60, 50, 40, 30, 20, 10) |
Tuple methods and built in functions
A tuple has only two methods of its own, count() and index(), because the others (append, remove, sort) would change it.
| Function | What it returns | Example | Result |
|---|---|---|---|
len(t) |
Number of elements | len((10, 20, 30, 40, 50)) |
5 |
tuple() |
An empty tuple | tuple() |
() |
tuple(seq) |
A tuple made from a string, list or range | tuple('aeiou') |
('a', 'e', 'i', 'o', 'u') |
tuple(seq) |
From a list | tuple([1, 2, 3]) |
(1, 2, 3) |
tuple(seq) |
From a range | tuple(range(5)) |
(0, 1, 2, 3, 4) |
t.count(x) |
How many times x appears |
(10,20,30,10,40,10,50).count(10) |
3 |
t.index(x) |
Index of the first x; ValueError if absent |
(10,20,30,40,50).index(30) |
2 |
sorted(t) |
A new sorted list, not a tuple; t is unchanged |
sorted(("Rama","Heena","Raj")) |
['Heena', 'Raj', 'Rama'] |
min(t), max(t), sum(t) |
Smallest, largest, total | sum((19,12,56,18,9,87,34)) |
235 |
Tuple assignment: unpacking
Tuple assignment lets you put a tuple of variables on the left of = and assign them values from a tuple on the right. The two sides must have the same number of items. If the right side is an expression, it is evaluated first, and then assigned.
| Code | What happens |
|---|---|
(num1, num2) = (10, 20) |
num1 is 10, num2 is 20 |
(name, rollNo, subject) = ("Pooja", 40, "CS") |
Three names receive the three values in order |
(num3, num4) = (10 + 5, 20 + 5) |
The right side becomes (15, 25) first |
(a, b, c, d) = (5, 6, 8) |
ValueError: not enough values to unpack (expected 4, got 3) |
Worked example: swapping without a temporary variable. Because the whole right side is computed before any name on the left changes, a, b = b, a swaps cleanly. The same idea gives a trap: what do a, b = 1, 2 followed by a, b = b, a + b give?
| Step | Right side evaluated first | Then assigned | a |
b |
|---|---|---|---|---|
| 1 | (1, 2) |
a, b = 1, 2 |
1 | 2 |
| 2 | (b, a + b) is (2, 3), using the old values |
a, b = 2, 3 |
2 | 3 |
The result is 2 3. If it had been done one name at a time (a = b then b = a + b), the second line would use the new a and give 4, which is the common wrong answer.
Nested tuples. A tuple of tuples is perfect for records, such as several students stored as st = ((101, "Aman", 98), (102, "Geet", 95)). Then st[0] is the first student's record, and st[0][1] is the name 'Aman'. A loop such as for i in range(0, len(st)) can print st[i][0], st[i][1] and st[i][2] as the columns.
Returning several values. A function can return a tuple, and unpacking receives it, so area, circumference = circle(5) works when circle returns (area, circumference). For a radius of 5 with 3.14 for $\pi$, the area is 78.5.
List or tuple?
| Feature | List | Tuple |
|---|---|---|
| Brackets | [ ] |
( ) (or none) |
| Mutable? | Yes | No |
| Methods | Many (append, remove, sort...) | Only count and index |
| Speed of iteration | Slower | Faster |
| Single element | [5] |
(5,) with the comma |
| Typical use | A collection that grows and changes | Fixed records and returned groups |
What is a dictionary?
A dictionary is a mapping: it connects a set of keys to a set of values. One key together with its value is called an item (a key value pair). A colon separates the key from its value, items are separated by commas, and the whole thing sits inside curly braces. Instead of a position, each key acts as the index.
| Code |
|---|
dict1 = {} |
dict2 = dict() |
dict3 = {'Mohan': 95, 'Ram': 89, 'Suhel': 92, 'Sangeeta': 85} |
The first two are empty dictionaries. In dict3, the names are the keys and the marks are the values. Two rules decide what is legal.
| Part | Rule | Examples |
|---|---|---|
| Keys | Unique, and of an immutable type | numbers, strings, tuples |
| Values | Any type; may repeat | numbers, strings, lists, dictionaries |
If you use the same key twice, the last value wins and only one item remains. So {'a': 1, 'b': 2, 'a': 3} has length 2 and equals {'a': 3, 'b': 2}. A list cannot be a key, because it is mutable: {[1]: 2} raises a TypeError.
Beyond the textbook. For the exam: keys must be of an immutable type. In reality: the precise rule is that a key must be hashable, which means Python must be able to compute a fixed number for it. A tuple is hashable only if everything inside it is. So (1, 2) works as a key, but (1, [2]) does not, even though it is a tuple. Dictionaries use this number to jump straight to the right item, which is why a lookup stays fast whatever the size.
Accessing, adding and changing items
Use the key in square brackets. If the key is absent, you get a KeyError. Assigning to a key that exists modifies the value, and assigning to a new key adds an item. Since the order of the items does not matter for lookup, dict3['Ram'] is always 89.
| Operation | Code | Effect |
|---|---|---|
| Read | dict3['Ram'] |
89 |
| Read a missing key | dict3['Shyam'] |
KeyError: 'Shyam' |
| Add | dict3['Meena'] = 78 |
New item at the end |
| Modify | dict3['Suhel'] = 93.5 |
Replaces 92 with 93.5 |
| Membership | 'Suhel' in dict3 |
True: in tests the keys |
| Membership of a value | 95 in dict3 |
False: 95 is a value, not a key |
Beyond the textbook. For the exam: a dictionary is accessed by key, never by position, so the order of items does not affect lookup. In reality: since Python 3.7, a dictionary also remembers the order in which items were inserted, so printing it or looping over it gives them back in that order. The textbook's own sample outputs show this. It is still not indexed by position: dict3[0] looks for a key named 0.
Traversing a dictionary
| Style | Code | Gives |
|---|---|---|
| Loop over the keys | for key in dict1: then dict1[key] |
Each key, and the value through it |
| Loop over the items | for key, value in dict1.items(): |
Each key and its value together |
The second style uses tuple unpacking: each item arrives as a (key, value) tuple and is unpacked into two names.
Dictionary methods and built in functions
| Method | What it does | Example | Result |
|---|---|---|---|
len(d) |
Number of key value pairs | len(dict1) |
4 |
dict(pairs) |
Builds a dictionary from a sequence of (key, value) pairs | dict([('Mohan',95),('Ram',89)]) |
{'Mohan': 95, 'Ram': 89} |
d.keys() |
All the keys | dict1.keys() |
dict_keys(['Mohan', 'Ram', 'Suhel', 'Sangeeta']) |
d.values() |
All the values | dict1.values() |
dict_values([95, 89, 92, 85]) |
d.items() |
All the (key, value) pairs as tuples | dict1.items() |
dict_items([('Mohan', 95), ...]) |
d.get(key) |
The value, or None if the key is absent (no error) |
dict1.get('Sohan') |
None |
d.update(d2) |
Adds the items of d2 into d (overwrites matching keys) |
dict1.update({'Sohan': 79}) |
dict1 gains Sohan |
del d[key] |
Deletes that item | del dict1['Ram'] |
Ram is gone |
del d |
Deletes the whole dictionary variable | del dict1 |
Later use: NameError |
d.clear() |
Removes all items, keeps the empty dictionary | dict1.clear() |
{} |
get or square brackets? d['Shyam'] stops the program with a KeyError when the key is missing, while d.get('Shyam') quietly returns None. The update() method changes only the dictionary it is called on, not the one passed in. And del d and d.clear() differ in one way: after clear() the empty dictionary still exists, but after del d the name itself is gone.
Beyond the textbook. For the exam: keys(), values() and items() return collections of the keys, values and pairs. In reality: they return view objects that stay linked to the dictionary. If you store k = d.keys() and later add an item to d, then k shows the new key as well. Wrap a view in list(...) when you want a fixed snapshot.
Worked example: a series of dictionary operations. Start with ODD = {1: 'One', 3: 'Three', 5: 'Five', 7: 'Seven', 9: 'Nine'}.
| Statement | Result |
|---|---|
ODD.keys() |
dict_keys([1, 3, 5, 7, 9]) |
len(ODD) |
5 |
7 in ODD |
True |
2 in ODD |
False |
ODD.get(9) |
'Nine' |
del ODD[9] |
ODD is now {1: 'One', 3: 'Three', 5: 'Five', 7: 'Seven'} |
Counting characters with a dictionary
A dictionary is the natural tool for counting, since each letter is a key and its count is the value. The logic: if the character is already a key, add 1; otherwise create it with the count 1.
Worked example: character frequency of 'banana'.
| Code |
|---|
st = 'banana' |
dic = {} |
for ch in st: |
if ch in dic: |
dic[ch] += 1 |
else: |
dic[ch] = 1 |
print(dic) |
| Pass | ch |
Already a key? | Action | dic afterwards |
|---|---|---|---|---|
| 1 | b | No | dic['b'] = 1 |
{'b': 1} |
| 2 | a | No | dic['a'] = 1 |
{'b': 1, 'a': 1} |
| 3 | n | No | dic['n'] = 1 |
{'b': 1, 'a': 1, 'n': 1} |
| 4 | a | Yes | dic['a'] += 1 |
{'b': 1, 'a': 2, 'n': 1} |
| 5 | n | Yes | dic['n'] += 1 |
{'b': 1, 'a': 2, 'n': 2} |
| 6 | a | Yes | dic['a'] += 1 |
{'b': 1, 'a': 3, 'n': 2} |
The common wrong step is to write dic[ch] += 1 for a letter that is not yet a key: that raises a KeyError, which is why the if ch in dic check comes first.
Worked example: number to words. A dictionary maps each digit to its word, and the function looks up each digit of the input in turn. The input is read as a string, so each character is converted with int(ch) to match the integer keys.
| Code |
|---|
def convert(num): |
numberNames = {0:'Zero', 1:'One', 2:'Two', 3:'Three', 4:'Four', 5:'Five', 6:'Six', 7:'Seven', 8:'Eight', 9:'Nine'} |
result = '' |
for ch in num: |
key = int(ch) |
result = result + ' ' + numberNames[key] |
return result |
For the input '6512' the loop makes four passes: the character '6' becomes the key 6 and adds ' Six', then '5' adds ' Five', '1' adds ' One' and '2' adds ' Two'. The returned text is ' Six Five One Two'. Without int(ch), the lookup numberNames['6'] would raise a KeyError, because the keys are integers and '6' is a string.
Choosing the right data type
| Need | Best choice | Why |
|---|---|---|
| A group of items that will grow or change | List | Mutable, many methods |
| A fixed record or several values returned together | Tuple | Immutable and faster |
| Look up a value by a name or code | Dictionary | The key finds the value directly |
| Characters of a word | String | Immutable sequence of characters |
Exam traps
| The trap | Why it's tempting | The truth |
|---|---|---|
(20) is a tuple |
Brackets look like a tuple | It is an int; the tuple is (20,) |
| Tuples cannot hold lists | They are "locked" | They can; the inner list stays editable |
sorted(t) returns a tuple |
The input was a tuple | It returns a list; the tuple is unchanged |
(a, b, c, d) = (5, 6, 8) fills what it can |
Python is forgiving elsewhere | ValueError: the counts must match |
d['x'] and d.get('x') behave alike |
Both look up a key | A missing key gives KeyError for brackets and None for get |
in checks values in a dictionary |
It does for a list | For a dictionary it checks keys |
| A repeated key keeps both items | Looks like two entries | Keys are unique; the last value replaces the earlier one |
| A list can be a key | Lists are common | Keys must be immutable (hashable); a list gives TypeError |
60-second revision
| Topic | Lock this in |
|---|---|
| Tuple | Ordered, immutable, round brackets or just commas; single element needs a comma |
| Inside a tuple | A mutable element (a list) can still change |
| Operations | + joins (new tuple), * repeats, in, slicing as in lists |
| Methods | Only count and index; sorted() returns a list; len, min, max, sum |
| Unpacking | Counts must match or ValueError; right side is evaluated first |
| Dictionary | Mapping of keys to values, curly braces, key: value items |
| Keys / values | Keys unique and immutable; values anything |
| Access | d[key] (KeyError if absent), d.get(key) (None if absent) |
| Add / modify | d[key] = value does both |
in |
Tests keys |
| Loop | for k in d or for k, v in d.items() |
| Methods | keys, values, items, get, update, del d[k], clear, len, dict |
Where this chapter connects
- Previous: Lists is the mutable cousin of the tuple, with the same indexing and slicing rules.
- Next: Societal Impact moves from programming to the effects of technology on society.
- Also related: Functions showed functions returning several values, which is a tuple at work, and Strings uses
partition(), which returns a tuple of three parts.
🎯 Practice MCQs
First 3 questions free · create a free account to unlock the rest — answers & explanations included, no payment needed
Q1. Consider: (1) a = (20) (2) b = (20,) (3) print(type(a), type(b)). What are the types printed, in order?
▸ Show answer & explanation
Answer: B
Brackets alone do not create a tuple, so (20) is the integer 20. The trailing comma in (20,) makes it a tuple. Option C is the usual wrong answer.
Q2. Consider: (1) t = (1, 2, 3, [8, 9]) (2) t[3][1] = 10 (3) print(t). What is printed?
▸ Show answer & explanation
Answer: B
The tuple itself is not modified, because it still holds the same list. The list inside is mutable, so its second element can be changed. A TypeError would occur only for something like t[0] = 5.
Q3. What type of value does sorted((3, 1, 2)) return?
▸ Show answer & explanation
Answer: C
The sorted function accepts any sequence and always returns a new list. The original tuple is not changed and tuples have no sort method.
🔒 12 more practice MCQs
Create a free account to unlock every MCQ in this chapter — answers and explanations included. No payment needed.
Already registered? Just log in and they'll all appear here.
Q4. Which statement raises an error?
▸ Show answer & explanation
Answer: C
Tuple assignment needs the same number of names and values. Option C has four names and three values, so a ValueError is raised. In option D the expressions are evaluated first and then assigned.
Q5. Consider: (1) a, b = 1, 2 (2) a, b = b, a + b (3) print(a, b). What is printed?
▸ Show answer & explanation
Answer: A
The right side (b, a + b) is evaluated first using the old values, which gives (2, 3). Only then are a and b assigned. Option B results from using the new value of a in the sum.
Q6. Match List I with List II. List I: (i) keys() (ii) items() (iii) get() with a missing key (iv) update(). List II: (p) returns None (q) returns the keys of the dictionary (r) returns the key and value pairs (s) merges the items of another dictionary.
▸ Show answer & explanation
Answer: A
The keys method gives the keys and items gives the pairs. A get call for an absent key returns None without an error, and update merges another dictionary into the one it is called on. Option B swaps keys and items.
Q7. For a dictionary d that does not contain the key 'Shyam', which expression returns None without raising an error?
▸ Show answer & explanation
Answer: B
The get method returns None for a missing key. Square brackets and del raise a KeyError, and a dictionary has no index method.
Q8. Consider: (1) d = {'Mohan': 95, 'Ram': 89} (2) print(95 in d, 'Ram' in d). What is printed?
▸ Show answer & explanation
Answer: C
The in operator on a dictionary checks the keys. The number 95 is a value, so the first test is False, while Ram is a key, so the second is True.
Q9. Assertion (A): A list cannot be used as a key in a dictionary. Reason (R): Dictionary keys must be of an immutable type.
▸ Show answer & explanation
Answer: A
A list is mutable, and keys must be immutable so that each key stays fixed. That rule is the reason a list is rejected with a TypeError.
Q10. Consider: (1) d = {'a': 1, 'b': 2, 'a': 3} (2) print(len(d), d['a']). What is printed?
▸ Show answer & explanation
Answer: C
Keys are unique, so the repeated key a keeps only the last value, 3. The dictionary then has two items, a and b. Options A and B count three items.
Q11. Consider: (1) dic = {} (2) for ch in 'banana': (3) if ch in dic: dic[ch] += 1 (4) else: dic[ch] = 1 (5) print(dic['a'], len(dic)). The if and else parts are inside the loop. What is printed?
▸ Show answer & explanation
Answer: A
The letters a, b and n become the keys, so the length is 3. The letter a occurs three times, so its count is 3. Option B uses the length of the string instead of the number of distinct letters.
Q12. Which of the following statements are correct? (i) The elements of a tuple cannot be reassigned. (ii) append() is a method of a tuple. (iii) Comma separated values without brackets form a tuple. (iv) A dictionary item is reached through its index position.
▸ Show answer & explanation
Answer: A
Statements (i) and (iii) are true. A tuple has no append method, and a dictionary item is reached through its key, not a position. So only option A is correct.
Q13. If t = (10, 20, 30, 40, 50, 60, 70, 80), what is t[::-3]?
▸ Show answer & explanation
Answer: A
A negative step starts from the last element, index 7, and moves three places left: indices 7, 4 and 1, giving 80, 50 and 20. Option B is t[::3] and option D starts one place early.
Q14. Consider: (1) d = {'x': 10, 'y': 20} (2) total = 0 (3) for k in d: total = total + d[k] (4) print(total). Statement (3) is a loop whose body is the addition. What is printed?
▸ Show answer & explanation
Answer: B
The loop over a dictionary gives its keys, and d[k] looks up the value for each. The values 10 and 20 are added to give 30. No key is missing, so no KeyError arises.
Q15. For tuple1 = (23, 1, 45, 67, 45, 9, 55, 45), what is the value of tuple1.index(45) + tuple1.count(45)?
▸ Show answer & explanation
Answer: A
The first 45 is at index 2, and 45 appears three times. So the sum is 2 + 3 = 5. Option B would result from using the index of the second 45.
📊 Previous-Year Questions
Practise with real CUET Computer Science previous-year papers — every question solved, with the correct answer and a step-by-step explanation.
View solved CUET PYQ papers →Ready to drill Computer Science?
Unlock all MCQs, chapter tests, mocks & PYQs for ₹199/year.
Get UniDrill Pro