Free Study Material
Every value you've stored so far held one single thing. A list holds many values together, in order, under one single variable name.
A list is an ordered, mutable collection of values, written inside square brackets [], separated by commas. A list can hold values of different types together, and its elements are reached using indexing and slicing, the same rules as a string.
marks = [78, 85, 92, 67, 74]
mixed = ["Aisha", 16, True]
print(marks)
print(marks[0])
print(marks[-1])
print(marks[1:4])
print(type(marks))
marks is a list of five integers. mixed holds a string, an integer, and a bool together — perfectly legal, a list doesn't require every element to share one type. marks[0] gives 78 (the first element); marks[-1] gives 74 (the last); marks[1:4] gives [85, 92, 67] — a slice, following the "stop is excluded" rule. type(marks) prints <class 'list'>.
Note: A list uses square brackets[ ]. Round brackets( )create a different type — a tuple — even though both are ordered collections.
Lists exist because most real data naturally comes as a collection, not a single value — a set of five test scores — and a list lets a program work with that entire collection under one name, instead of a separate variable per value.
A list is an ordered, mutable collection written in square brackets, able to hold mixed data types, accessed using the same indexing and slicing rules as strings.
A List is a standard Python data type that stores an ordered sequence of items. It is defined by placing items inside square brackets [ ], separated by commas.
Method 1: Square Brackets (Recommended)
Examples:
empty = []nums = [10, 20, 30]data = ["Amit", 101, 95.5]# Creating a list of Computer Science topics
topics = ["Python", "SQL", "Networking", "Security"]
# 1. Forward Indexing (0, 1, 2, 3)
print("First Topic [0]:", topics[0]) # Output: Python
print("Third Topic [2]:", topics[2]) # Output: Networking
# 2. Backward Indexing (-1, -2...)
# -1 is always the LAST item
print("Last Topic [-1]:", topics[-1]) # Output: Security
print("Second Last [-2]:", topics[-2]) # Output: Networking
list[start : stop : step]
Note: If you omit 'start', it starts at 0. If you omit 'stop', it goes to the end.
# Our list: ["Python", "SQL", "Networking", "Security"]
# Indices: 0 1 2 3
# Slice from index 1 up to (but not including) 3
sub_group = topics[1:3]
print("Sliced List:", sub_group)
# Output: ['SQL', 'Networking']
# Demonstrating Mutability
prices = [100, 200, 300]
print("Before:", prices)
# Change the middle price (Index 1) to 999
prices[1] = 999
print("After:", prices)
# Output: [100, 999, 300]
Lists support the same general operators strings do, plus traversal with a for loop.
+) — joins two lists into a new one.*) — repeats a list's elements.in / not in) — checks whether a value exists in a list.for loop.group_a = [1, 2, 3]
group_b = [4, 5]
print(group_a + group_b)
print(group_a * 2)
print(3 in group_a)
for value in group_a:
print("Value:", value)
group_a + group_b gives [1, 2, 3, 4, 5]. group_a * 2 gives [1, 2, 3, 1, 2, 3] — the elements repeated twice, not each number doubled. 3 in group_a is True. The for loop then prints each of group_a's three values on its own line.
Note:group_a * 2repeats the list's elements — it does not multiply each individual number by2.
List traversal with for value in group_a: works exactly like string traversal — one pass per element, in order — the same loop pattern applies to every collection type.
Lists support +, * (repetition of the whole list, not its values), in/not in, and len(). for element in list: traverses every element in order.
The + operator joins two lists end-to-end to create a new list. It does not change the original lists.
The * operator repeats the list items a specific number of times.
# 1. Concatenation (Joining)
# We have two separate teams
team_A = ["Alice", "Bob"]
team_B = ["Charlie", "David"]
# Join them into one big team
all_teams = team_A + team_B
print("Combined:", all_teams)
# Output: ['Alice', 'Bob', 'Charlie', 'David']
# 2. Repetition (Multiplying)
# Create a list of 5 zeros quickly
zeros = [0] * 5
print("Zeros:", zeros)
# Output: [0, 0, 0, 0, 0]
item in list_name
# Shopping List
cart = ["Milk", "Eggs", "Bread"]
# Check if 'Eggs' are in the cart
if "Eggs" in cart:
print("You have Eggs!")
# Check if 'Butter' is missing
if "Butter" not in cart:
print("Warning: You forgot Butter.")
Use this when you just want to read or print the items. It is cleaner and easier to write.
Use this when you need to change the items in the list. You need the index (position number) to update the value.
# Method 1: Direct Access
# Best for printing or reading data
scores = [90, 85, 88]
print("--- Scores ---")
for s in scores:
print(s)
# Method 2: Index Access
# Goal: Add 5 bonus marks to every score
scores = [90, 85, 88]
n = len(scores) # Total items: 3
print("Original:", scores)
# Loop from 0 to 2
for i in range(n):
# Update the item at index 'i'
scores[i] = scores[i] + 5
print("Updated:", scores)
# Output: [95, 90, 93]
A list being mutable means it can actually change after creation — this topic covers adding new elements, and overwriting an existing one.
value as one new element at the end.value at a specific position, shifting later elements right.other_list individually onto the end.my_list[i] = new_value overwrites the element at that position in place.fruits = ["apple", "banana"]
fruits.append("mango")
fruits.insert(1, "kiwi")
fruits.extend(["grape", "fig"])
fruits[0] = "orange"
print(fruits)
append("mango") adds it at the end. insert(1, "kiwi") inserts at index 1, pushing later elements over. extend(["grape", "fig"]) adds both as separate elements. fruits[0] = "orange" overwrites the first element in place. The final result: ['orange', 'kiwi', 'banana', 'mango', 'grape', 'fig'].
Warning:fruits.append(["grape", "fig"])(usingappendinstead ofextend) adds the entire two-item list as one single element —append()never unpacks its argument.
fruits[0] = "orange" really does change the original list object in memory, with no new list created — exactly the mutability this data type promises, and strings never allow.
append(value) adds one element at the end; insert(index, value) adds at a position; extend(other_list) adds each element of another list; my_list[i] = new_value overwrites in place — all four change the original list directly.
list_name.append(item)
Note: It modifies the list in place and returns None. Do not write L = L.append(x)!
# 1. Using append()
fruits = ["Apple", "Banana"]
print("Original:", fruits)
# Add 'Cherry' to the end
fruits.append("Cherry")
print("After Append:", fruits)
# Output: ['Apple', 'Banana', 'Cherry']
list_name.extend(another_list)
It takes an iterable (like a list or tuple) and appends each element to the list.
# 2. Using extend()
bucket_A = ["Red", "Blue"]
bucket_B = ["Green", "Yellow"]
# Pour bucket_B into bucket_A
bucket_A.extend(bucket_B)
print("Extended List:", bucket_A)
# Output: ['Red', 'Blue', 'Green', 'Yellow']
# Comparison
list_1 = [1, 2]
list_2 = [3, 4]
# If we used APPEND:
# list_1.append(list_2)
# Result: [1, 2, [3, 4]] <- Nested List!
# If we used EXTEND:
# list_1.extend(list_2)
# Result: [1, 2, 3, 4] <- Flat List
list_name.insert(index, item)
# 3. Using insert()
ranks = ["First", "Third"]
# Oops, we missed "Second"!
# Insert "Second" at index 1
ranks.insert(1, "Second")
print("Corrected:", ranks)
# Output: ['First', 'Second', 'Third']
Just as elements can be added, they can be removed — Python gives four different ways, each suited to a different situation.
value. Raises ValueError if not present.index; with no argument, removes the last element.index (a statement, returns nothing).scores = [55, 70, 70, 90, 40]
scores.remove(70)
last = scores.pop()
del scores[0]
print(scores, "| removed:", last)
remove(70) deletes only the first 70 it finds, leaving the second one: [55, 70, 90, 40]. pop() removes and returns the last element, 40, leaving [55, 70, 90]. del scores[0] removes 55, leaving [70, 90]. Final output: [70, 90] | removed: 40.
Note:remove()searches by value;pop()anddelact by index.scores.remove(0)would try to delete the value0, not the element at index0.
pop() is the one removal method that hands back what it deleted — the right choice whenever the removed value is still needed afterwards.
remove(value) deletes the first matching value; pop(index) deletes by position and returns it; del list[index] deletes by position without returning anything; clear() empties the list completely.
list_name.remove(value)
Warning: If the value is NOT found, Python raises a ValueError (Crash). Always check with in first!
# 1. Using remove()
cart = ["Milk", "Bread", "Milk", "Butter"]
# We want to remove 'Milk'
# Only the FIRST 'Milk' (Index 0) is gone
cart.remove("Milk")
print("Cart:", cart)
# Output: ['Bread', 'Milk', 'Butter']
variable = list_name.pop(index)
Key Feature: It returns the removed item so you can store it in a variable.
# 2. Using pop()
tasks = ["Homework", "Cleaning", "Cooking"]
# Remove the last item (Cooking) and save it
done_task = tasks.pop()
print("Finished:", done_task) # Output: Cooking
print("Remaining:", tasks) # Output: ['Homework', 'Cleaning']
# Remove specific index (0)
tasks.pop(0)
print("After removing first task:", tasks) # Output: ['Cleaning']
# 3. Using del and clear()
data = [10, 20, 30, 40, 50]
# Delete index 2 (Value 30)
del data[2]
print("After del:", data) # [10, 20, 40, 50]
# Delete a SLICE (Indices 0 to 2)
del data[0:2]
print("After slice del:", data) # [40, 50]
# Clear everything
data.clear()
print("After clear:", data) # []
| Method | Action | Returns Value? |
|---|---|---|
remove(x) |
Deletes first 'x' | No |
pop(i) |
Deletes index 'i' | Yes |
del L[i] |
Deletes index 'i' | No |
Python provides ready-made functions that work on a whole list at once — summarising it, or putting it in order — without a hand-written loop.
Both accept reverse=True for descending order.
marks = [67, 92, 45, 88, 71]
print(min(marks), max(marks), sum(marks))
marks.sort()
print(marks)
original = [67, 92, 45]
new_list = sorted(original, reverse=True)
print(original, new_list)
min/max/sum give 45 92 363. marks.sort() rearranges marks itself: [45, 67, 71, 88, 92]. sorted(original, reverse=True) returns a brand-new descending list, [92, 67, 45], while original prints completely unchanged: [67, 92, 45].
Warning:marks.sort()returnsNone— writingmarks = marks.sort()throws away the entire list.sort()changes the list itself; it does not hand back a sorted copy.
sort() and sorted() do the same job but disagree on what they touch: sort() changes its own list and returns nothing; sorted() leaves its input alone and returns a new one.
len(), min(), max(), sum() summarise a list. sort() rearranges in place and returns nothing; sorted() returns a new sorted list without changing the original — both accept reverse=True.
len(list)
Returns the total count of items.
sum(list)
Returns the total sum of all numbers.
min(list)
Returns the smallest value.
max(list)
Returns the largest value.
# A list of student marks
marks = [55, 98, 76, 42, 88]
print("Total Students:", len(marks)) # 5
print("Highest Mark:", max(marks)) # 98
print("Lowest Mark:", min(marks)) # 42
print("Total Sum:", sum(marks)) # 359
# Calculate Average (Mean)
average = sum(marks) / len(marks)
print("Average Score:", average) # 71.8
# 1. Reverse
numbers = [1, 2, 3, 4]
numbers.reverse()
print("Reversed:", numbers) # Output: [4, 3, 2, 1]
# 2. Sort (Ascending by default)
data = [10, 5, 20, 1]
data.sort()
print("Sorted:", data) # Output: [1, 5, 10, 20]
# 3. Sort (Descending)
data.sort(reverse=True)
print("Descending:", data) # Output: [20, 10, 5, 1]
If you want to keep the original order but need a sorted version for calculation, use sorted().
If you want to permanently reorder the list, use sort().
# Demonstration: sort() vs sorted()
original = [3, 1, 2]
# Using sorted() - SAFE
new_list = sorted(original)
print("Original stays same:", original) # [3, 1, 2]
print("New List is sorted:", new_list) # [1, 2, 3]
# Using sort() - DESTRUCTIVE
original.sort()
print("Original is changed:", original) # [1, 2, 3]
You've already used in to check whether a value exists in a list. This topic goes further — finding exactly where a value is, and how many times it occurs.
value. Raises ValueError if not present.value occurs.grades = ["B", "A", "C", "A", "B", "A"]
print(grades.index("A"))
print(grades.count("A"))
print(grades.count("D"))
grades.index("A") returns 1 — the position of the first "A", even though it appears again at positions 3 and 5. grades.count("A") returns 3. grades.count("D") returns 0 — count() never raises an error for a missing value; it simply reports zero occurrences.
Note:count()returning0andindex()raising aValueErrorfor a missing value are two different, deliberate behaviours — checkvalue in my_listfirst if you're not sureindex()will succeed.
index() answers "where is it, at minimum?" while count() answers "how many are there, in total?" — two genuinely different questions about the same list.
index(value) returns the position of a value's first occurrence, raising ValueError if missing; count(value) returns how many times a value occurs, returning 0 (never an error) if missing.
list_name.index(item)
Critical Warning: If the item is NOT found, Python raises a ValueError (Crash). Always check if the item exists using in before asking for its index!
# 1. Using index()
grades = ["A", "B", "A", "C", "A"]
# Find where the FIRST "B" is
pos = grades.index("B")
print("B is at index:", pos) # Output: 1
# Find where the FIRST "A" is
# Notice it stops at index 0 and ignores the rest
print("First A is at:", grades.index("A")) # Output: 0
list_name.count(item)
# 2. Using count()
grades = ["A", "B", "A", "C", "A"]
# How many A's?
total_As = grades.count("A")
print("Total A grades:", total_As) # Output: 3
# How many F's? (Not in list)
print("Total F grades:", grades.count("F")) # Output: 0
A list's elements can themselves be lists — this is how Python represents table-like data, such as rows of student records. This closing topic covers reading nested lists, then puts the chapter to work in a complete program.
A nested list is a list containing other lists as elements. Reaching an element inside an inner list needs two indexes: outer[i][j] — the first selects which inner list, the second selects the position inside it.
students = [
["Aisha", 91],
["Rahul", 78],
["Meera", 85]
]
topper = students[0]
for record in students:
if record[1] > topper[1]:
topper = record
print("Topper:", topper[0], "with", topper[1], "marks")
students[0][0] would reach "Aisha"; students[1][1] would reach 78. The loop traverses the outer list one row at a time, comparing each record's mark (record[1]) against the best found so far (topper[1]), replacing topper whenever a higher one appears. By the end, topper holds ['Aisha', 91], so the program prints Topper: Aisha with 91 marks.
Note: This "start with the first item, then replace it whenever something better is found" pattern is the standard way to find a maximum by hand, without using max().
Traversing a nested list with for record in students: visits one inner list per pass — exactly the standard way to process table-like data such as a list of student records, reached with two indexes rather than one.
A nested list is a list of lists, read with two indexes (outer[i][j]) — traversing one with for record in outer_list: visits one inner list per pass, the standard technique for finding a value (like the highest mark) across rows of data.
Example Matrix:
| Col 0 | Col 1 | |
| Row 0 | 10 | 20 |
| Row 1 | 30 | 40 |
To access 30: matrix[1][0]
# Creating a 3x3 Matrix
matrix = [
[1, 2, 3], # Row 0
[4, 5, 6], # Row 1
[7, 8, 9] # Row 2
]
# Accessing elements
print("Row 1, Col 2:", matrix[1][2]) # Output: 6
print("Row 0, Col 0:", matrix[0][0]) # Output: 1
# Modifying an element
matrix[2][0] = 99
print("Modified Row 2:", matrix[2]) # Output: [99, 8, 9]
# Program: Linear Search
numbers = [10, 50, 30, 70, 80, 20]
target = 70
found = False
for i in range(len(numbers)):
if numbers[i] == target:
print("Found", target, "at Index:", i)
found = True
break # Stop searching once found
if found == False:
print(target, "not found in list.")
# Program: Count Frequency
data = [1, 2, 1, 3, 1, 4, 1]
search_item = 1
count = 0
for item in data:
if item == search_item:
count = count + 1
print("Number", search_item, "appears", count, "times.")
# Program: Find Max, Min, and Mean manually
values = [45, 88, 12, 67, 99, 34]
# Initialize variables with the first item
max_val = values[0]
min_val = values[0]
total_sum = 0
for x in values:
# Check Max
if x > max_val:
max_val = x
# Check Min
if x < min_val:
min_val = x
# Add to Total
total_sum = total_sum + x
mean_val = total_sum / len(values)
print("Maximum:", max_val)
print("Minimum:", min_val)
print("Mean (Average):", mean_val)