📓 Python Programming - Data Structures
1. Lists
Lists in Python: - Ordered, mutable (can be changed) collection of items.
- Can store mixed data types.
# Creating a list
fruits = ["apple", "banana", "cherry"]
print(fruits)
➤ Indexing, Slicing & Negative Indexing:
# Indexing
print(fruits[0]) # First item
print(fruits[-1]) # Last item
# Slicing
print(fruits[0:2]) # First two items
➤ Looping Through Lists & Conditions:
for fruit in fruits:
if fruit.startswith("b"):
print(f"{fruit} starts with 'b'")
➤ Useful List Methods:
# Adding items
fruits.append("orange")
print(fruits)
fruits.insert(1, "mango")
print(fruits)
# Removing items
fruits.remove("banana")
print(fruits)
# Sorting
fruits.sort()
print(fruits)
➤ More List Methods & Operations:
# More list methods
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print("Original list:", numbers)
# Count occurrences
print("Count of 1:", numbers.count(1))
# Find index
print("Index of 4:", numbers.index(4))
# Extend (vs append)
numbers.extend([7, 8]) # Adds multiple items
print("After extend:", numbers)
# Reverse
numbers.reverse()
print("After reverse:", numbers)
# Clear
temp_list = [1, 2, 3]
temp_list.clear()
print("After clear:", temp_list)
# Copy (shallow vs deep)
original = [1, [2, 3], 4]
shallow_copy = original.copy()
deep_copy = original[:] # Simple way for lists
print("Original:", original)
print("Shallow copy:", shallow_copy)
# List concatenation and repetition
list1 = [1, 2, 3]
list2 = [4, 5, 6]
combined = list1 + list2
print("Combined:", combined)
repeated = [0] * 5
print("Repeated:", repeated)
➤ List Comprehension with Conditions:
# Create list of squares for even numbers from 0 to 10
squares = [x**2 for x in range(11) if x % 2 == 0]
print(squares)
➤ Nested Lists (2D Lists):
# Creating a 2D list (matrix)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print("Matrix:", matrix)
# Accessing elements
print("Element at [1][2]:", matrix[1][2])
# Iterating through 2D list
print("All elements:")
for row in matrix:
for element in row:
print(element, end=" ")
print() # New line after each row
# Using enumerate for indices
print("With indices:")
for i, row in enumerate(matrix):
for j, element in enumerate(row):
print(f"[{i}][{j}] = {element}")
# List comprehension for 2D
flattened = [element for row in matrix for element in row]
print("Flattened:", flattened)
# Creating a 2D list with comprehension
multiplication_table = [[i * j for j in range(1, 4)] for i in range(1, 4)]
print("Multiplication table:", multiplication_table)
2. Tuples
Tuples: - Ordered, immutable collection.
-
Faster than lists.
-
Suitable for fixed data.
# Creating a tuple
dimensions = (10, 20, 30)
print(dimensions)
# Indexing and Slicing
print(dimensions[1])
print(dimensions[:2])
# Looping
for dim in dimensions:
print(dim)
➤ More Tuple Operations:
# Tuple methods
numbers = (1, 2, 3, 2, 4, 2, 5)
print("Original tuple:", numbers)
print("Count of 2:", numbers.count(2))
print("Index of 3:", numbers.index(3))
# Tuple concatenation
tuple1 = (1, 2, 3)
tuple2 = (4, 5, 6)
combined = tuple1 + tuple2
print("Combined tuple:", combined)
# Tuple repetition
repeated = (0,) * 5 # Note the comma for single element tuple
print("Repeated tuple:", repeated)
# Single element tuple (important!)
single = (42,) # Comma is required
not_tuple = (42) # This is just an integer
print("Single element tuple:", single, type(single))
print("Not a tuple:", not_tuple, type(not_tuple))
# Nested tuples
nested = ((1, 2), (3, 4), (5, 6))
print("Nested tuple:", nested)
print("Access nested element:", nested[1][0])
# Named tuples (from collections module)
from collections import namedtuple
# Define a named tuple
Point = namedtuple('Point', ['x', 'y'])
Student = namedtuple('Student', ['name', 'age', 'grade'])
# Create instances
p = Point(10, 20)
student = Student('Alice', 20, 'A')
print("Point:", p)
print("Access by name:", p.x, p.y)
print("Student:", student)
print("Student name:", student.name)
➤ List vs Tuple:
-
List: Mutable → You can modify contents.
-
Tuple: Immutable → Contents cannot be changed.
-
Lists have more built-in methods compared to tuples.
-
Use lists for homogeneous items and tuples for heterogeneous items.
➤ Switching Between Lists and Tuples:
# List to Tuple
my_list = [1, 2, 3]
my_tuple = tuple(my_list)
print(my_tuple)
# Tuple to List
new_list = list(my_tuple)
print(new_list)
➤ Tuple Unpacking:
person = ("Alice", 25, "Engineer")
name, age, profession = person
print(name, age, profession)
3. Sets
Sets: - Unordered collection of unique items.
- Used for mathematical operations like union, intersection, etc.
➤ Basic Set Operations:
# Creating sets
colors = {"red", "green", "blue"}
print(colors)
# Adding, Removing, Discarding
colors.add("yellow")
print(colors)
colors.remove("green") # Raises error if not present
print(colors)
colors.discard("purple") # No error if not present
print(colors)
➤ More Set Operations & Methods:
# Set from list (removes duplicates)
numbers = [1, 2, 2, 3, 3, 3, 4, 5]
unique_numbers = set(numbers)
print("Original list:", numbers)
print("Unique set:", unique_numbers)
# Set methods
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
print("Set1:", set1)
print("Set2:", set2)
# Union (all elements)
print("Union (|):", set1 | set2)
print("Union method:", set1.union(set2))
# Intersection (common elements)
print("Intersection (&):", set1 & set2)
print("Intersection method:", set1.intersection(set2))
# Difference (elements in set1 but not in set2)
print("Difference (-):", set1 - set2)
print("Difference method:", set1.difference(set2))
# Symmetric difference (elements in either set, but not both)
print("Symmetric difference (^):", set1 ^ set2)
print("Symmetric difference method:", set1.symmetric_difference(set2))
# Subset and superset checks
small_set = {1, 2}
print("Is {1, 2} subset of set1?", small_set.issubset(set1))
print("Is set1 superset of {1, 2}?", set1.issuperset(small_set))
# Disjoint sets (no common elements)
set3 = {10, 11, 12}
print("Are set1 and set3 disjoint?", set1.isdisjoint(set3))
# Set comprehension
even_squares = {x**2 for x in range(10) if x % 2 == 0}
print("Even squares:", even_squares)
➤ Set Operations:
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print("Union:", a | b)
print("Intersection:", a & b)
print("Difference:", a - b)
➤ Frozenset vs Set:
-
set→ Mutable -
frozenset→ Immutable
fs = frozenset([1, 2, 3])
print(fs)
4. Dictionaries
Dictionaries: - Collection of key-value pairs.
- Keys must be unique.
➤ Creating & Accessing:
student = {"name": "Alice", "age": 22, "grade": "A"}
print(student["name"])
➤ Useful Dictionary Methods:
# Get with default
print(student.get("age"))
print(student.get("major", "Not specified"))
# Update
student.update({"grade": "A+", "major": "CS"})
print(student)
# Keys, Values
print(student.keys())
print(student.values())
# Pop
student.pop("age")
print(student)
➤ More Dictionary Methods & Operations:
# Dictionary from lists
keys = ['name', 'age', 'city']
values = ['Bob', 25, 'London']
person = dict(zip(keys, values))
print("Dictionary from lists:", person)
# Dictionary methods
inventory = {'apples': 50, 'bananas': 30, 'cherries': 20}
print("Original inventory:", inventory)
# Items, keys, values iteration
print("Items:")
for item in inventory.items():
print(item)
print("Key-value pairs:")
for key, value in inventory.items():
print(f"{key}: {value}")
# Popitem (removes and returns last item)
last_item = inventory.popitem()
print("Popped item:", last_item)
print("After popitem:", inventory)
# Setdefault (get or set default value)
inventory.setdefault('oranges', 0)
print("After setdefault:", inventory)
# Dictionary merging (Python 3.9+)
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
# merged = dict1 | dict2 # Python 3.9+
merged = {**dict1, **dict2} # Works in older versions
print("Merged dictionary:", merged)
# Dictionary with default values
from collections import defaultdict
dd = defaultdict(int) # Default value is 0
dd['a'] += 1
dd['b'] += 2
print("Default dict:", dict(dd))
# Counter (specialized dictionary)
from collections import Counter
text = "hello world"
char_count = Counter(text)
print("Character count:", char_count)
print("Most common:", char_count.most_common(3))
➤ Dictionary Comprehension:
# Squares of numbers
squares = {x: x**2 for x in range(5)}
print(squares)
# Filtering even squares
even_squares = {k: v for k, v in squares.items() if v % 2 == 0}
print(even_squares)
➤ Nested Dictionaries:
# Student with nested details
student = {
"name": "Alice",
"subjects": {"Math": 90, "Science": 95}
}
print(student["subjects"]["Math"])
🎯 Quick Recap
✅ Lists → Ordered, mutable
✅ Tuples → Ordered, immutable
✅ Sets → Unordered, unique items
✅ Dictionaries → Key-value pairs
✅ Use list/dictionary comprehension for concise code
5. Additional Data Structures
Python provides several specialized data structures in the collections module:
# Deque (double-ended queue)
from collections import deque
# Create a deque
dq = deque([1, 2, 3, 4, 5])
print("Original deque:", dq)
# Add to both ends
dq.appendleft(0)
dq.append(6)
print("After adding to both ends:", dq)
# Remove from both ends
left_item = dq.popleft()
right_item = dq.pop()
print(f"Removed {left_item} from left, {right_item} from right")
print("After removal:", dq)
# Rotate
dq.rotate(2) # Rotate right by 2
print("After rotating right by 2:", dq)
# OrderedDict (remembers insertion order)
from collections import OrderedDict
od = OrderedDict()
od['first'] = 1
od['second'] = 2
od['third'] = 3
print("OrderedDict:", od)
# Move to end
od.move_to_end('first')
print("After moving 'first' to end:", od)
# ChainMap (combines multiple dictionaries)
from collections import ChainMap
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
dict3 = {'e': 5, 'f': 6}
chain = ChainMap(dict1, dict2, dict3)
print("ChainMap:", chain)
print("Value of 'a':", chain['a'])
print("All keys:", list(chain.keys()))
6. Performance & When to Use Each Structure
Time Complexity Comparison:
| Operation | List | Tuple | Set | Dictionary |
|---|---|---|---|---|
| Access by index | O(1) | O(1) | N/A | N/A |
| Access by key | N/A | N/A | N/A | O(1) |
| Search | O(n) | O(n) | O(1) | O(1) |
| Insert | O(n) | N/A | O(1) | O(1) |
| Delete | O(n) | N/A | O(1) | O(1) |
When to Use Each: - List: When you need ordered, mutable data with duplicates - Tuple: When you need ordered, immutable data (coordinates, database records) - Set: When you need unique elements and fast membership testing - Dictionary: When you need key-value mapping with fast lookups
# Practical examples of when to use each structure
# Example 1: Shopping cart (List - ordered, allows duplicates)
shopping_cart = ['apple', 'banana', 'apple', 'orange']
print("Shopping cart:", shopping_cart)
# Example 2: GPS coordinates (Tuple - immutable, fixed structure)
locations = [
('New York', 40.7128, -74.0060),
('London', 51.5074, -0.1278),
('Tokyo', 35.6762, 139.6503)
]
print("Locations:", locations)
# Example 3: Unique visitors (Set - no duplicates)
unique_visitors = {'user1', 'user2', 'user1', 'user3'}
print("Unique visitors:", unique_visitors)
# Example 4: User profiles (Dictionary - key-value mapping)
user_profiles = {
'user1': {'name': 'Alice', 'age': 25},
'user2': {'name': 'Bob', 'age': 30},
'user3': {'name': 'Charlie', 'age': 35}
}
print("User profiles:", user_profiles)
# Memory usage comparison
import sys
list_data = [1, 2, 3, 4, 5]
tuple_data = (1, 2, 3, 4, 5)
set_data = {1, 2, 3, 4, 5}
dict_data = {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}
print(f"List memory: {sys.getsizeof(list_data)} bytes")
print(f"Tuple memory: {sys.getsizeof(tuple_data)} bytes")
print(f"Set memory: {sys.getsizeof(set_data)} bytes")
print(f"Dict memory: {sys.getsizeof(dict_data)} bytes")
7. Converting Between Data Structures
Converting between different data structures is often necessary:
# Converting between data structures
original_list = [1, 2, 3, 2, 4, 5]
print("Original list:", original_list)
# List to other structures
list_to_tuple = tuple(original_list)
list_to_set = set(original_list) # Removes duplicates
print("List to tuple:", list_to_tuple)
print("List to set:", list_to_set)
# Tuple to other structures
tuple_to_list = list(list_to_tuple)
tuple_to_set = set(list_to_tuple)
print("Tuple to list:", tuple_to_list)
print("Tuple to set:", tuple_to_set)
# Set to other structures
set_to_list = list(list_to_set)
set_to_tuple = tuple(list_to_set)
print("Set to list:", set_to_list)
print("Set to tuple:", set_to_tuple)
# Dictionary conversions
sample_dict = {'a': 1, 'b': 2, 'c': 3}
print("Original dict:", sample_dict)
# Dictionary to lists/tuples/sets
dict_keys = list(sample_dict.keys())
dict_values = list(sample_dict.values())
dict_items = list(sample_dict.items())
print("Dict keys:", dict_keys)
print("Dict values:", dict_values)
print("Dict items:", dict_items)
# Lists to dictionary
keys = ['name', 'age', 'city']
values = ['Alice', 25, 'Boston']
list_to_dict = dict(zip(keys, values))
print("Lists to dict:", list_to_dict)
# List of tuples to dictionary
tuple_list = [('x', 1), ('y', 2), ('z', 3)]
tuples_to_dict = dict(tuple_list)
print("Tuples to dict:", tuples_to_dict)
# String to other structures
text = "hello"
string_to_list = list(text)
string_to_tuple = tuple(text)
string_to_set = set(text) # Removes duplicate characters
print("String to list:", string_to_list)
print("String to tuple:", string_to_tuple)
print("String to set:", string_to_set)
📝 Practice Exercises
Basic Exercises:
-
Create a list of your favorite 5 movies and sort them.
-
Convert a list of numbers to a tuple and unpack the first three numbers.
-
Find common elements between two sets.
-
Create a dictionary for a book with title, author, and year. Add a genre to it.
-
Use dictionary comprehension to map numbers from 1 to 5 to their cubes.
Intermediate Exercises:
-
Create a 2D list representing a 3x3 matrix and print it row by row.
-
Remove duplicates from a list while preserving order (without using set).
-
Create a word frequency counter using a dictionary.
-
Use set operations to find students taking both Math and Science courses.
-
Implement a simple phone book using nested dictionaries.
Advanced Exercises:
-
Create a function that flattens a nested list of any depth.
-
Build a simple inventory system using dictionaries and lists.
-
Use collections.Counter to analyze text and find the most common words.
-
Create a student grading system with multiple subjects and calculate averages.
-
Implement a simple cache system using dictionaries.
Challenge Exercises:
-
Create a data structure to represent a family tree using nested dictionaries.
-
Build a simple database system that can store and query student records.
-
Implement a text-based menu system for a restaurant using data structures.
-
Create a library management system with books, authors, and borrowers.
-
Build a simple social network representation using dictionaries and sets.