Home / Computer Science / Class XI / Working with Lists and Dictionaries
Working with Lists and Dictionaries — CUET Computer Science hero
Class XI 💻 Computer Science Ch 15 of 19

Working with Lists and Dictionaries

CUET unit: Working with Lists and Dictionaries

📌 Snapshot

  • Lists and dictionaries in Python: slicing, methods and key lookups, with line by line output prediction.
  • Why append and extend differ, why sort changes a list but sorted does not, and why a missing key raises an error.
  • Every list method and dictionary method in one table each, with the exact value it returns.
  • Four complete data handling programs traced step by step, from averages to counting characters.

📖 Detailed Notes

Written and reviewed by Rohit Singh, Computer Science & Commerce faculty at UniDrill (MCA, Osmania University · 6 years teaching). Based on NCERT Informatics Practices Class XI, Chapter 4.

One variable, many values

A single variable holding a single number cannot store the marks of 40 students or the phone numbers in your contacts. Python gives you two containers for this job. A list is an ordered row of items you reach by position. A dictionary is a lookup table you reach by name. Most output prediction questions in this chapter are about what happens to the container after each statement, so the skill to build is tracing: write the container down, apply one statement, write it again.

Feature List Dictionary
Brackets Square [ ] Curly { }
Holds Single items Key value pairs
You reach an item by Index (position, from 0) Key
Mutable? Yes Yes
Duplicates Allowed Keys must be unique, values may repeat
Example [2, 4, 6, 8] {'Mohan': 95, 'Ram': 89}

Lists: ordered and mutable

A list is an ordered sequence of one or more elements, enclosed in square brackets and separated by commas. Unlike a string, which holds only characters, a list can hold elements of different data types: integers, floats, strings, tuples or even another list (a nested list).

Code
list1 = [2, 4, 6, 8, 10, 12]
list3 = [100, 23.5, 'Hello']
list4 = [['Physics', 101], ['Chemistry', 202], ['Mathematics', 303]]
print(list3)
Output
[100, 23.5, 'Hello']

Indexing: forward and backward

Each element has an index. The first element has index 0, the second 1, and so on. Negative indices count from the end, so -1 is the last element. An index that does not exist raises an IndexError.

Index 0 1 2 3 4 5
Element of [2, 4, 6, 8, 10, 12] 2 4 6 8 10 12
Negative index -6 -5 -4 -3 -2 -1

The index can be any expression that gives an integer. With n = len(list1), the last element is list1[n-1] and the first element is list1[-n].

Worked example: indexing. Let list1 = [2, 4, 6, 8, 10, 12].

Expression Value Reason
list1[0] 2 First element
list1[3] 8 Index 3 is the fourth element
list1[1+4] 12 1+4 is 5
list1[-1] 12 Last element
list1[-n] with n = 6 2 -6 is the first element
list1[15] IndexError Only indices 0 to 5 (and -6 to -1) exist

The common wrong step is to read list1[6] as the last element of a six element list. The last valid positive index is len(list1) - 1, which is 5.

Lists are mutable. You can change an element after the list is created, in the same list.

Code
list1 = ['Red', 'Green', 'Blue', 'Orange']
list1[3] = 'Black'
print(list1)
Output
['Red', 'Green', 'Blue', 'Black']

List operations

Operation Symbol What it does Example Result
Concatenation + Joins lists [1, 3] + [2, 4] [1, 3, 2, 4]
Repetition * Repeats the contents ['Hello'] * 4 ['Hello', 'Hello', 'Hello', 'Hello']
Membership in True if the element is present 'Green' in ['Red', 'Green'] True
Non membership not in True if the element is absent 'Cyan' not in ['Red', 'Green'] True
Slicing [start:stop:step] Makes a new list from part of a list see below

Concatenation does not change the original lists. It creates a new list, so to keep the result you must assign it, for example new_list = list1 + list2. The + operator needs a list on both sides. Joining a list and a string raises a TypeError.

Pause and predict: after a = [1, 2, 3] and b = [4], you write a + b on its own line. What are a and b afterwards?

Check your answer: unchanged. a is still [1, 2, 3] and b is still [4]. The joined list [1, 2, 3, 4] was created and then thrown away because it was not assigned to anything.

Slicing: the stop index is never included

Slicing takes out a part of a list as a new list. In list1[start:stop:step], the slice begins at start, stops before stop, and moves by step. A missing start means the beginning, a missing stop means the end, and a missing step means 1.

Why the stop is excluded. list1[2:6] has $6 - 2 = 4$ elements. With the stop excluded, the number of elements is simply stop minus start, and list1[:3] + list1[3:] rebuilds the whole list without overlap.

Worked example: slicing. Let list1 = ['Red', 'Green', 'Blue', 'Cyan', 'Magenta', 'Yellow', 'Black']. Indices are 0 to 6.

Expression Result Reason
list1[2:6] ['Blue', 'Cyan', 'Magenta', 'Yellow'] Indices 2, 3, 4, 5
list1[2:20] ['Blue', 'Cyan', 'Magenta', 'Yellow', 'Black'] Stop beyond the end is cut to the end of the list
list1[7:2] [] Start is after stop, so the slice is empty
list1[:5] ['Red', 'Green', 'Blue', 'Cyan', 'Magenta'] Start is missing, so it is 0
list1[0:6:2] ['Red', 'Blue', 'Magenta'] Indices 0, 2, 4
list1[-6:-2] ['Green', 'Blue', 'Cyan', 'Magenta'] Indices 1 to 4
list1[::2] ['Red', 'Blue', 'Magenta', 'Black'] Every second element of the whole list
list1[::-1] ['Black', 'Yellow', 'Magenta', 'Cyan', 'Blue', 'Green', 'Red'] Negative step reads backwards

An out of range slice never raises an error, but an out of range single index does. That is the usual trap.

Beyond the textbook. For the exam: a slice makes a new list, and a stop beyond the end is cut off. In reality: the same notation works on strings and tuples, and list1[::-1] is the standard way to reverse a copy of any sequence without changing the original. Why it matters: once you read [start:stop:step] fluently, a whole family of questions on strings, tuples and later chapters becomes the same question.

Traversing a list

To traverse a list means to visit every element. There are two ways with a for loop.

Code
list1 = ['Red', 'Green', 'Blue']
for item in list1:
    print(item)
for i in range(len(list1)):
    print(list1[i])

Both loops print Red, Green and Blue, one per line, so six lines in total. The first loop gives you the element. The second gives you the index, and you read the element with list1[i]. Use the second form when you need the position too. range(len(list1)) runs from 0 to the length minus one, which are exactly the valid indices.

List methods and built in functions

A method is a function that belongs to an object and is called with a dot, as in list1.append(50). The most testable fact about methods is what they return and whether they change the list.

Method or function What it does Changes the list? Returns
len(list1) Number of elements No An integer
list() With no argument, an empty list. With a sequence, a list of its elements No (makes a new list) A list
append(x) Adds one element at the end. If x is a list, it is added as a single element Yes None
extend(list2) Adds each element of list2 at the end Yes None
insert(i, x) Puts x at index i, shifting the rest right Yes None
count(x) How many times x appears No An integer
index(x) Index of the first occurrence. Raises ValueError if absent No An integer
remove(x) Removes the first occurrence of the value x. Raises ValueError if absent Yes None
pop(i) Removes and gives back the element at index i. With no argument, the last element Yes The removed element
reverse() Reverses the order in place Yes None
sort() Sorts in place, ascending. sort(reverse = True) sorts descending Yes None
sorted(list1) Makes a new sorted list No A new list
min(), max(), sum() Smallest, largest, total No A value

append versus extend.

Code
list1 = [10, 20, 30, 40]
list1.append([50, 60])
print(list1)
list2 = [10, 20, 30]
list2.extend([40, 50])
print(list2)
Output
[10, 20, 30, 40, [50, 60]]
[10, 20, 30, 40, 50]

append adds one item, even if that item is itself a list, so the length grows by 1. extend adds each item of the other list, so the length grows by the length of the other list.

remove versus pop. remove(30) deletes the value 30 (its first occurrence only). pop(3) deletes the item at index 3 and gives it back. For [10, 20, 30, 40, 50, 30], remove(30) leaves [10, 20, 40, 50, 30].

sort versus sorted. sort() rearranges the list itself. sorted() leaves the original alone and makes a new list.

Code
list1 = [23, 45, 11, 67, 85, 56]
list2 = sorted(list1)
print(list1)
print(list2)
list1.sort(reverse = True)
print(list1)
Output
[23, 45, 11, 67, 85, 56]
[11, 23, 45, 56, 67, 85]
[85, 67, 56, 45, 23, 11]

Why the return value matters. sort() returns None. If you write list1 = list1.sort(), list1 becomes None and you have lost your data. The same holds for append, extend, insert, remove and reverse. They change the list and return nothing useful.

Worked example: trace a sequence of methods. Start with list1 = [10, 20, 30, 40, 50].

Code
list1.insert(2, 25)
list1.pop()
list1.remove(10)
list1.extend([60, 70])
list1.reverse()
print(list1)
Statement List after the statement Note
start [10, 20, 30, 40, 50]
list1.insert(2, 25) [10, 20, 25, 30, 40, 50] 25 goes at index 2
list1.pop() [10, 20, 25, 30, 40] Last element 50 removed and returned
list1.remove(10) [20, 25, 30, 40] First 10 removed
list1.extend([60, 70]) [20, 25, 30, 40, 60, 70] Two elements added
list1.reverse() [70, 60, 40, 30, 25, 20] Order reversed in place

The printed output is [70, 60, 40, 30, 25, 20]. The common wrong step is to print list1.reverse() expecting a reversed list. That prints None.

Worked example: predict the output. These are typical questions on slices, sort, sorted and del.

Code
list1 = [12, 32, 65, 26, 80, 10]
list1.sort()
print(list1)
list1 = [12, 32, 65, 26, 80, 10]
sorted(list1)
print(list1)
myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
del myList[3:]
print(myList)
myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
del myList[::2]
print(myList)
Output
[10, 12, 26, 32, 65, 80]
[12, 32, 65, 26, 80, 10]
[1, 2, 3]
[2, 4, 6, 8, 10]

The second output is the original order because sorted(list1) builds a new list that was not stored. The del myList[::2] removes indices 0, 2, 4, 6 and 8, so the elements 2, 4, 6, 8 and 10 remain.

Beyond the textbook. For the exam: sort() works on a list of numbers or a list of strings. In reality: sorting a list that mixes numbers and strings, such as [3, 'a', 1], raises a TypeError, because Python cannot decide whether 3 is smaller than 'a'. Why it matters: "sorting needs comparable items" is an easy way to explain an error message if one appears in a question.

Pause and predict: a = [3, 1, 2] and then b = a.sort(). What are a and b?

Check your answer: a is [1, 2, 3] and b is None. The method sorted a itself and returned nothing.

List programs

Worked example: average of marks. The program reads n marks into a list and then adds them up. Suppose n = 5 and the marks are 45, 89, 79, 76 and 55.

Code
list1 = []
n = int(input("How many students: "))
for i in range(0, n):
    marks = int(input("Enter marks: "))
    list1.append(marks)
total = 0
for marks in list1:
    total = total + marks
average = total / n
print("Average marks of", n, "students is:", average)
Output
Average marks of 5 students is: 68.8
Step What happens Result
1 Start with an empty list []
2 The first loop appends five marks [45, 89, 79, 76, 55]
3 The second loop adds each mark to total $45 + 89 + 79 + 76 + 55 = 344$
4 Divide by n $344 / 5 = 68.8$

Worked example: search a list. The program searches for a number and reports its position (counting from 1). With the list [23, 567, 12, 89, 324] and the searched number 12:

Code
list1 = [23, 567, 12, 89, 324]
num = 12
position = -1
for i in range(0, len(list1)):
    if list1[i] == num:
        position = i + 1
if position == -1:
    print("Number", num, "is not present in the list")
else:
    print("Number", num, "is present at", position, "position")
Output
Number 12 is present at 3 position

The variable position starts at -1 as a flag meaning "not found". The match happens at index 2, so position becomes 3 and the else branch prints it. The common wrong step is to print position + 1 again and report 4.

A menu driven list program. The chapter's longest program shows a menu and runs one operation based on the choice. The pattern is one if, many elif branches and a final else for an invalid choice. Each branch calls one method.

Choice Operation Method used
1 Append an element append()
2 Insert an element at a position insert()
3 Append a list extend()
4 Modify an element assignment myList[i] = newElement
5 Delete by position pop()
6 Delete by value remove()
7 and 8 Sort ascending or descending sort() and sort(reverse = True)
9 Display print()

Starting from [22, 4, 16, 38, 13], choice 8 sorts in reverse and gives [38, 22, 16, 13, 4], and then choice 5 with position 2 pops 16 and gives [38, 22, 13, 4]. Programs like this check the position first (if i < len(myList)), because a position past the end would cause an IndexError.

Dictionaries: key value pairs

A dictionary is a mapping between a set of keys and a set of values. Each key value pair is an item. A colon separates a key from its value, items are separated by commas, and the whole thing is in curly braces.

Rules for dictionary keys. Keys must be unique and of an immutable type: a number, a string or a tuple. Values can repeat and can be of any type, including mutable ones.

Code
dict3 = {'Mohan': 95, 'Ram': 89, 'Suhel': 92, 'Sangeeta': 85}
print(dict3['Ram'])
print(dict3['Shyam'])
Output
89
KeyError: 'Shyam'

Why you use keys, not positions. The key 'Ram' always maps to 89, wherever the item sits in the dictionary. The key acts as the index. Asking for a key that does not exist raises a KeyError.

Beyond the textbook. For the exam: a dictionary is a mapping that you read by key, not by position, and it is described as an unordered collection. In reality: in current Python versions a dictionary remembers the order in which items were added, so printing it shows them in insertion order. Lookup is still always by key. Why it matters: you never need position to read a value, so the exam answer and the real behaviour never conflict in a question that asks you to predict output.

Membership. The operator in checks the keys, not the values.

Code
dict1 = {'Mohan': 95, 'Ram': 89, 'Suhel': 92, 'Sangeeta': 85}
print('Suhel' in dict1)
print(92 in dict1)
print('Suhel' not in dict1)
Output
True
False
False

The second line is False because 92 is a value, not a key.

Dictionaries are mutable. Assigning to a new key adds an item. Assigning to an existing key overwrites its value.

Code
dict1 = {'Mohan': 95, 'Ram': 89, 'Suhel': 92, 'Sangeeta': 85}
dict1['Meena'] = 78
dict1['Suhel'] = 93.5
print(dict1)
Output
{'Mohan': 95, 'Ram': 89, 'Suhel': 93.5, 'Sangeeta': 85, 'Meena': 78}

Pause and predict: d = {'a': 1, 'b': 2}, then d['b'] = 5 and d['c'] = 7. What is len(d)?

Check your answer: 3. The key 'b' already existed, so its value was replaced and no item was added. The key 'c' is new, so it adds one item. The dictionary holds a, b and c.

Traversing a dictionary

Code
dict1 = {'Mohan': 95, 'Ram': 89}
for key in dict1:
    print(key, ':', dict1[key])
for key, value in dict1.items():
    print(key, ':', value)
Output
Mohan : 95
Ram : 89
Mohan : 95
Ram : 89
Method The loop variable holds Value is read by
for key in dict1 Each key dict1[key]
for key, value in dict1.items() Each key and its value together The variable value

Dictionary methods and built in functions

Method What it does Example with dict1 = {'Mohan':95, 'Ram':89, 'Suhel':92, 'Sangeeta':85}
len() Number of key value pairs len(dict1) gives 4
dict() Builds a dictionary from a sequence of key value pairs dict([('Mohan', 95), ('Ram', 89)]) gives {'Mohan': 95, 'Ram': 89}
keys() The keys dict_keys(['Mohan', 'Ram', 'Suhel', 'Sangeeta'])
values() The values dict_values([95, 89, 92, 85])
items() The key value pairs as tuples dict_items([('Mohan', 95), ('Ram', 89), ...])
get(key) The value for the key, or None if the key is absent dict1.get('Sangeeta') gives 85 and dict1.get('Sohan') gives None
update(dict2) Adds the items of dict2 to the dictionary (and overwrites matching keys) Adds the two items of dict2, and dict2 itself is unchanged
clear() Removes every item Leaves {}
del dict1[key] Removes the item with that key del dict1['Ram'] leaves three items
del dict1 Removes the whole dictionary from memory Afterwards dict1 gives a NameError

get versus square brackets. dict1['Sohan'] raises a KeyError for a missing key, but dict1.get('Sohan') returns None quietly. Use get when the key might be absent.

clear versus del. After dict1.clear() the dictionary still exists and is empty ({}). After del dict1 the name itself is gone.

Beyond the textbook. For the exam: keys(), values() and items() give the keys, values and key value pairs, and the output is printed as dict_keys([...]) and so on. In reality: these return special view objects, not ordinary lists. Wrap them in list() if you need a list, for example list(dict1.keys()). Why it matters: it explains the dict_keys( wrapper in the output and why you cannot index the result directly.

Worked example: the ODD dictionary. Build ODD = {1:'One', 3:'Three', 5:'Five', 7:'Seven', 9:'Nine'} and predict.

Statement Output Why
ODD.keys() dict_keys([1, 3, 5, 7, 9]) The keys
ODD.values() dict_values(['One', 'Three', 'Five', 'Seven', 'Nine']) The values
len(ODD) 5 Five items
7 in ODD True 7 is a key
2 in ODD False 2 is not a key
ODD.get(9) 'Nine' Value for key 9
del ODD[9] then ODD {1: 'One', 3: 'Three', 5: 'Five', 7: 'Seven'} The item for key 9 is gone

Worked example: state capitals. With stateCapital = {"Assam":"Guwahati", "Bihar":"Patna", "Maharashtra":"Mumbai", "Rajasthan":"Jaipur"}:

Statement Output
print(stateCapital.get("Bihar")) Patna
print(len(stateCapital)) 4
print("Maharashtra" in stateCapital) True
del stateCapital["Assam"] then print(stateCapital) {'Bihar': 'Patna', 'Maharashtra': 'Mumbai', 'Rajasthan': 'Jaipur'}

Dictionary programs

Worked example: count characters. The program counts how many times each character appears in a string. For the input HelloWorld:

Code
st = input("Enter a string: ")
dic = {}
for ch in st:
    if ch in dic:
        dic[ch] += 1
    else:
        dic[ch] = 1
for key in dic:
    print(key, ':', dic[key])
Output
H : 1
e : 1
l : 3
o : 2
W : 1
r : 1
d : 1

Why it works. The dictionary starts empty. For each character, if it is already a key, add 1 to its count. If not, create the key with count 1. In HelloWorld, the letter l appears at three places (in "Hello" twice and in "World" once), so its count goes 1, 2, 3. The letter o appears twice, and every other letter once. The capital H and W are separate keys from any lower case letters because Python is case sensitive.

Worked example: number to words. A dictionary maps each digit to its word, and the program converts each character of the input.

Code
num = input("Enter any number: ")
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)
    value = numberNames[key]
    result = result + ' ' + value
print("The number is:", num)
print("The numberName is:", result)
Output
The number is: 6512
The numberName is: Six Five One Two
Step ch key value result after the step
1 '6' 6 Six ' Six'
2 '5' 5 Five ' Six Five'
3 '1' 1 One ' Six Five One'
4 '2' 2 Two ' Six Five One Two'

The step key = int(ch) is needed because input() gives a string of characters, but the dictionary keys are integers. Without it, numberNames['6'] would raise a KeyError. The extra space before "Six" in the output comes from the way result is built.

Worked example: employees and salaries. The program stores name : salary pairs by assigning employee[name] = salary inside a loop. It reads n names and salaries, and then prints each item using for k in employee: print(k, employee[k]). With names Tarun, Amina and Joseph and salaries 12000, 34000 and 24000, the dictionary becomes three items, one per employee, and the loop prints them in the order they were stored.

Exam traps

The trap Why it's tempting The truth
"list1[len(list1)] is the last element." Length feels like the last position The last index is len(list1) - 1. The former raises an IndexError
"A slice stop value is included." Slice [2:6] looks like 2 to 6 The stop is excluded: indices 2 to 5
"sorted(list1) changes list1." Both sort sort() changes the list. sorted() returns a new one
"append([4, 5]) adds two elements." Two numbers are inside It adds one element, the list [4, 5]. extend adds two
"list1.sort() returns the sorted list." It sorts, so it must return it It returns None
"remove(2) deletes the element at index 2." Pop uses an index remove deletes by value, pop deletes by index
"index() is called find() for lists." Strings have find() Lists use index() and raise ValueError if absent
"in checks values of a dictionary." It does for lists It checks keys
"A list can be a dictionary key." Lists are common containers Keys must be immutable: numbers, strings or tuples
"A missing key gives None with dict1['x']." get does Square brackets raise a KeyError. Only get() returns None

60-second revision

Topic Lock this in
List Ordered, mutable, square brackets, mixed types allowed, can be nested
Index Forward from 0, backward from -1, out of range gives IndexError
Operators + joins lists only · * repeats · in and not in test membership
Slice [start:stop:step] · stop excluded · out of range slice is fine · [::-1] reverses
Add elements append one item · extend many items · insert(i, x) at index
Remove elements remove(x) by value · pop(i) by index returns it · del list1[a:b] by slice
Order sort() in place, returns None · sorted() new list · reverse() in place
Summary functions len, min, max, sum, count, index
Dictionary Mapping of unique immutable keys to values, curly braces, read by key
Missing key d[key] gives KeyError · d.get(key) gives None
Membership in tests keys
Dictionary methods keys, values, items, get, update, clear, del d[key], len
Counting pattern if ch in d: d[ch] += 1 else: d[ch] = 1

Where this chapter connects

🎯 Practice MCQs

First 3 questions free · create a free account to unlock the rest — answers & explanations included, no payment needed

Q1. Consider: (1) L = [10, 20, 30, 40, 50] (2) print(L[-2], L[1]). What is printed?

▸ Show answer & explanation

Answer: A

L[-2] is the second element from the end, which is 40, and L[1] is the second element from the start, which is 20. Option B uses -3, C uses index 0 and D swaps the values.

Q2. Consider: (1) L = [5, 10, 15, 20, 25, 30] (2) print(L[1:4]). What is printed?

▸ Show answer & explanation

Answer: A

The slice starts at index 1 and stops before index 4, so it takes the elements at indices 1, 2 and 3. Option B includes the stop index, and C and D start at the wrong index.

Q3. Consider: (1) L = [1, 2, 3, 4, 5] (2) print(L[::-1]). What is printed?

▸ Show answer & explanation

Answer: B

A step of -1 with no start or stop reads the whole list from the end to the beginning. Option C would need a step of -2, and D drops the last element.

🔒 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.

📊 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