Python Data Structures: Lists,
Tuples, Dictionaries & Mutability
Unit 2
Mutable vs Immutable Objects
• Mutable: Can be changed (List, Dictionary, Set)
• Immutable: Cannot be changed (Tuple, String,
Number)
• Example: list is mutable, tuple is immutable
# Mutable (list)
a = [1, 2, 3]
a[0] = 99
print(a) # [99, 2, 3]
# Immutable (string)
s = "hello"
# s[0] = "H" # ❌ Error: strings are immutable
Lists – Creating and Initializing
• Lists are ordered, mutable, allow duplicates
• Created using [] or list()
• Examples:
my_list = [1, 2, 3, 4, 5]
Lists Are Heterogeneous
• Python lists store object references
• Python is dynamically typed
• No fixed data type restriction
• Examples:
– My_list=[10, “Python”, 3.14, True]
– My_list=[100, “Hi”, [1.2],(3,4),{“a”:1}, greet]
Lists – Accessing, Slicing, Traversing
• Indexing:
print(my_list[0]) # 1
print(my_list[-1]) # 5
• Slicing:
print(my_list[1:4]) # [2, 3, 4]
print(my_list[:3]) # [1, 2, 3]
print(my_list[::2]) # [1, 3, 5]
• Traversal:
for item in my_list:
print(item, end=" ") # 1 2 3 4 5
List Operations
• Length: print(len(my_list)) # 5
• Concatenation:
list1 = [1, 2]
list2 = [3, 4]
print(list1 + list2) # [1, 2, 3, 4]
• Repetition: print(list1 * 3) # [1, 2, 1, 2, 1, 2]
• Membership:
– print(2 in list1) # True
– print(5 not in list1) # True
• max(), min(), sum(),
– nums = [3, 1, 5, 7]
– print(max(nums)) # 7
– print(min(nums)) # 1
– print(sum(nums)) # 16
• all(), any()
– print(all([True, 1, 5])) # True (all non-zero)
– print(all([0, 1, 2])) # False (0 is False)
– print(any([0, 0, 5])) # True (at least one True)
List Methods – Part 1
• append(x): add element at end
• my_list.append(6)
• print(my_list) # [1, 2, 3, 4, 5, 6]
• extend([x,y]): add multiple elements
• my_list.extend([7, 8])
• print(my_list) # [1, 2, 3, 4, 5, 6, 7, 8]
• count(x): count occurrences
• print(my_list.count(2)) # 1
• remove(x): remove first occurrence
• my_list.remove(3)
• print(my_list) # [1, 2, 4, 5, 6, 7, 8]
List Methods – Part 2
• index(x): find index of value
• print(my_list.index(4)) # 2
• pop([i]): remove by index (default last)
• print(my_list.pop()) # 8 (last element removed)
• print(my_list) # [1, 2, 4, 5, 6, 7]
• insert(i,x): insert at index
• my_list.insert(2, 99)
• print(my_list) # [1, 2, 99, 4, 5, 6, 7]
• sort(): sort list in place
• unsorted = [5, 2, 8, 1]
• [Link]()
• print(unsorted) # [1, 2, 5, 8]
• reverse(): reverse order
• [Link]()
• print(unsorted) # [8, 5, 2, 1]
Cloning a List
• Cloning is essential when you want to modify
a copy without affecting the original list.
• Slicing:
• new_list = old_list[:]
• The .copy() method:
• new_list = old_list.copy()
• List Comprehension:
• new_list = [item for item in old_list]
Tuple
• A tuple is an immutable ordered collection of
elements.
• Unlike lists, tuples cannot be modified (no
adding, removing, or updating elements).
• Useful when data should remain constant.
Tuples – Creating
• Ordered, immutable, allow duplicates
• Defined with () or tuple()
• Examples:
# Empty tuple
t1 = ()
# Tuple with integers
t2 = (1, 2, 3)
# Mixed data types
t3 = (10, "Hello", 3.14)
# Without parentheses (tuple packing)
t4 = 1, 2, 3
# Single element tuple → needs a comma
t5 = (5,)
Tuple Operations
• Length:
• t = (1, 2, 3, 4)
• print(len(t)) # 4
• Concatenation:
• t1 = (1, 2)
• t2 = (3, 4)
• print(t1 + t2) # (1, 2, 3, 4)
• Repetition:
• print(t1 * 3) # (1, 2, 1, 2, 1, 2)
• Membership:
• print(2 in t1) # True
• print(5 not in t1) # True
• max(t), min(t)
• nums = (3, 1, 7, 2)
• print(max(nums)) # 7
• print(min(nums)) # 1
Tuple Methods
• count(x): count occurrences
• t = (1, 2, 2, 3, 4, 2)
• print([Link](2)) # 3
• index(x): return first index of element
• t = (10, 20, 30, 20, 40)
• print([Link](20)) # 1
Dictionaries
• A dictionary is an unordered collection of
key-value pairs.
• Keys must be unique and immutable (like
strings, numbers, tuples).
• Values can be of any data type and can be
duplicated.
Dictionaries – Creating
• Unordered, mutable, key-value pairs
• Keys must be unique and immutable
# Empty dictionary
d1 = {}
# Dictionary with key-value pairs
d2 = {"name": "Alice", "age": 25,
"city": "Delhi"} •Nested Literal:
```python inventory = {
# Using dict() constructor "apples": {"qty": 10,
d3 = dict(id=101, dept="CS", "price": 0.5}, "bananas":
marks=90) {"qty": 20, "price": 0.3} }
print(d2)
Dictionaries – Access, Add, Modify, Delete
• Access: d['key'], [Link]('key')
• print(d2["name"]) # Alice
• print([Link]("age")) # 25
• Modify: d['age'] = 30
• d2["age"] = 26
• print(d2) # {'name': 'Alice', 'age': 26, 'city': 'Delhi', 'gender':
'Female'}
• Delete: del d['age'], [Link]('name')
• # Delete specific key
• del d2["city"]
• # Remove with pop()
• [Link]("gender")
• # Remove all items
• [Link]()
Traversing Dictionary
my_dict = { "brand": "Ford", "model":
"Mustang", "year": 1964 }
• Keys():By default, iterating over a dictionary directly traverses its
keys
print("--- Traversing Keys ---")
for key in my_dict: print(key) # Alternative using .keys() for explicit clarity
for key in my_dict.keys():
print(key)
• Values():To iterate through the values, you can access the value
using the key within the loop, or use the .values() method
print("--- Traversing Values ---")
for key in my_dict:
print(my_dict[key])
# Alternative using .values() for direct value
access
for value in my_dict.values():
print(value)
Traversing Dictionaries
• Traversing Both Keys and Values
print("--- Traversing Both Keys and Values ---")
for key, value in my_dict.items():
print(f"{key}: {value}")
• Traversing in Sorted Order
print("--- Traversing in Sorted Order by Key
---") for key in sorted(my_dict):
print(f"{key}: {my_dict[key]}")
• Traversing Nested Dictionaries
nested_dict = {
"user1": {"name": "Alice", "age": 30},
"user2": {"name": "Bob", "age": 25}
}
print("--- Traversing Nested Dictionaries ---")
for user_id, user_details in nested_dict.items():
print(f"User ID: {user_id}")
for detail_key, detail_value in user_details.items():
print(f" {detail_key}: {detail_value}")
Dictionary Methods
• len(d), str(d)
• d = {"a": 1, "b": 2}
• print(len(d)) # 2
• clear(): remove all items
• [Link]()
• print(d) # {}
• copy(): shallow copy
• d = {"x": 10, "y": 20}
• d_copy = [Link]()
• print(d_copy) # {'x': 10, 'y': 20}
• get(key, default)
• print([Link]("x")) # 10
• print([Link]("z", "NA")) # NA (default if key not found)
• update({}): merge dictionaries
• [Link]({"z": 30, "y": 25})
• print(d) # {'x': 10, 'y': 25, 'z': 30}
Difference Between List and Dictionary
Feature List Dictionary
Ordered collection of Unordered collection
Definition
elements of key-value pairs
By key (e.g.,
Access By index (e.g., list[0])
dict["name"])
Integer indices Custom keys (string,
Keys/Index
(0,1,2,…) number, tuple)
Mutability Mutable Mutable
Allows duplicate Keys must be unique;
Duplicates
elements values can repeat
Mapping relationships
Use case Sequence of items
(key ↔ value)
Tuple as a Return Value
• Tuples allow a function to return multiple pieces of data at once. Python
packs them automatically, and you can "unpack" them in one line.
def get_circle_info(radius): """ Calculates and returns the circumference and area of
a circle. Returns: (circumference, area) """
pi = 3.14159
circumference = 2 * pi * radius
area = pi * radius * radius # Python automatically packs these two values into a
tuple
return circumference, area # Calling the function and storing the result in a
single variable (a tuple)
result_tuple = get_circle_info(10)
print(f"Result as a tuple: {result_tuple}")
print(f"Type of result: {type(result_tuple)}") # Calling the function and unpacking
the values into separate variables
circumference, area = get_circle_info(10)
print(f"Circumference: {circumference}")
print(f"Area: {area}")
Sets
• a set is an unordered collection of unique
elements. Unlike lists or tuples, sets do not
allow duplicate values i.e. each element in a set
must be unique. Sets are mutable, meaning you
can add or remove items after a set has been
created.
• Sets are defined using curly braces {} or the
built-in set() function. They are particularly
useful for membership testing, removing
duplicates from a sequence, and performing
common mathematical set operations like
union, intersection, and difference.
my_set = {1, 2, 3, 4, 5}
print (my_set)
Sets
• Functions: you can create a set using
the set() function by passing an
iterable.
my_set = set([1, 2, 3, 4, 5])
print (my_set)
• Different data types:
mixed_set = {1, 'hello', (1, 2, 3)}
print (mixed_set)
Sets
• Add new element
my_set = {1, 2, 3} # Adding an element 4
to the set
my_set.add(4)
print (my_set)
• Removing Elements from a Set
my_set.remove(3)
print (my_set)
• discard() function: Unlike remove(), discard() does
not raise an error if the element is not found in the
set
my_set.discard(5)
print (my_set)
• Membership in a Set
my_set = {1, 2, 3, 4}
if 2 in my_set:
print("2 is present in the
set")
else:
print("2 is not present in
the set")
Set Operations
• Union − It combine elements from both sets
using the union() function or the | operator.
• Intersection − It is used to get common elements
using the intersection() function or
the & operator.
• Difference − It is used to get elements that are
in one set but not the other using the
difference() function or the - operator.
• Symmetric Difference − It is used to get elements
that are in either of the sets but not in both
using the symmetric_difference() method or
the ^ operator.
Python Set Comprehensions
• Set comprehensions in Python is a concise
way to create sets based on iterable
objects, similar to list comprehensions. It is
used to generate sets by applying an
expression to each item in an iterable.
• Set comprehensions are useful when you
need to create a set from the result of
applying some operation or filtering
elements from another iterable.
• Syntax: set_variable = {expression for
item in iterable if condition}
creating a set containing the squares of numbers from 1
to 5 using a set comprehension −
squared_set = {x**2 for x in range(1, 6)}
print(squared_set)
• Filtering Elements Using Set Comprehensions:
include conditional statements
even_set = {x for x in range(1, 11) if x % 2 == 0}
print(even_set)
• Nested Set Comprehensions
nested_set = {(x, y) for x in range(1, 3) for y in range(1, 3)}
print(nested_set)
• Output: {(1, 1), (1, 2), (2, 1), (2, 2)}
Frozen Sets
• frozen set is an immutable collection
of unique elements, similar to a
regular set but with the distinction
that it cannot be modified after
creation.
• my_frozen_set = frozenset([1, 2, 3])
print(my_frozen_set)
my_frozen_set.add(4)
frozenset({1, 2, 3}) Traceback (most recent call last): File
"/home/cg/root/664b2732e125d/[Link]", line 3, in <module>
my_frozen_set.add(4) AttributeError: 'frozenset' object has no attribute 'add'
Access Set
• Using loop
for s in my_set: # my_set={1,2,3,4}
print (s) # print each value on newline
• Using List Comprehension
ac_items = [item for item in my_set]
print(ac_items)
• Subset from a set
• Using Set Operations − You can use built-in set
operations such as issubset() function to check
if one set is a subset of another.
• Iterating Over Power Set − Iterate over all
possible subsets of the set and filter based on
certain criteria to access specific subsets.
Subset example
import itertools # Defining a set
# Checking if {1, 2} is a subset of the original set
original_set = {1, 2, 3, 4}
subset = {1, 2}.issubset(original_set)
print("{1, 2} is a subset of the original set:",
subset)
# Generating all subsets with two elements
subsets_with_two_elements = [set(subset) for
subset in [Link](original_set,
2)]
print("Subsets with two elements:",
subsets_with_two_elements)
Membership in sets
# Defining a set
langs = {"C", "C++", "Java", "Python"}
# Checking if an item exists in the set
if "Java" in langs:
print("Java is present in the set.")
else:
print("Java is not present in the set.")
# Checking if an item does not exist in the set
if "SQL" not in langs:
print("SQL is not present in the set.")
else:
print("SQL is present in the set.")
Set
• Add new value:
– my_set.add(5)
– My_set.update([5])
What would be the output of the following code:
Set1={“Hello”}
[Link](“World”)
Print(set1)
Union
• The union of two sets contains all unique
elements from both sets.
set_A={1,2,3,4,5}
set_B={6,7,8,9}
print(set_A | set_B) # Output: {1, 2, 3, 4, 5, 6,
7, 8, 9} (order may vary)
print(set_A.union(set_B)) # Output: {1, 2, 3,
4, 5, 6, 7, 8, 9}
Set Intersection Operator (&)
• The intersection of two sets AA and BB, denoted by A∩B,
consists of all elements that are common to both in A and
B. For example: {1,2}∩{2,3}={2}
set1 = {1, 2, 3}
set2 = {3, 4, 5}
set3 = {6, 8, 9}
set4 = {9, 8, 73}
intersection_set1 = [Link](set2)
intersection_set2 = set3 & set4
print ('The intersection of set1 and set2 is',
intersection_set1)
print ('The intersection of set3 and set4 is',
intersection_set2)
The intersection of set1 and set2 is {3}
The intersection of set3 and set4 is {8, 9}
Set Difference Operator (-)
• The difference (subtraction) between two sets consists of
elements present in the first set but not in the second set
set1 = {1, 2, 3}
set2 = {3, 4, 5}
set3 = {6, 8, 9}
set4 = {9, 8, 73}
difference_set1 = [Link](set2)
difference_set2 = set3 - set4
print ('The difference between set1 and set2 is',
difference_set1)
print ('The difference between set3 and set4 is',
difference_set2)
The difference between set1 and set2 is {1, 2}
The difference between set3 and set4 is {6}
Python Set Symmetric Difference
Operator
• The symmetric difference of two sets consists of
elements that are present in either set but not
in both sets. The symmetric difference of A and
B is denoted by "A Δ B” and is defined by − A Δ B
= (A − B) ⋃ (B − A)
• Method: set1.symmetric_difference(set2)
• If A = {1, 2, 3, 4, 5, 6, 7, 8} and B = {1, 3, 5,
6, 7, 8, 9}, then
A Δ B = {2, 4, 9}