Data Structures in Python¶
Python provides several built-in data structures for storing and organizing data.
Lists¶
Lists are ordered, mutable sequences that can contain different types of elements.
Creating Lists
# Empty list
empty_list = []
# List with elements
numbers = [1, 2, 3, 4, 5]
fruits = ["apple", "banana", "cherry"]
mixed = [1, "hello", 3.14, True]
List Operations
fruits = ["apple", "banana", "cherry"]
# Access elements
print(fruits[0]) # apple
print(fruits[-1]) # cherry
# Modify elements
fruits[1] = "orange"
print(fruits) # ['apple', 'orange', 'cherry']
# Add elements
fruits.append("grape")
print(fruits) # ['apple', 'orange', 'cherry', 'grape']
# Insert at specific position
fruits.insert(1, "mango")
print(fruits) # ['apple', 'mango', 'orange', 'cherry', 'grape']
# Remove elements
fruits.remove("orange")
print(fruits) # ['apple', 'mango', 'cherry', 'grape']
# Remove by index
popped = fruits.pop(2)
print(popped) # cherry
print(fruits) # ['apple', 'mango', 'grape']
List Slicing
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numbers[2:5]) # [2, 3, 4]
print(numbers[:5]) # [0, 1, 2, 3, 4]
print(numbers[5:]) # [5, 6, 7, 8, 9]
print(numbers[::2]) # [0, 2, 4, 6, 8]
print(numbers[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
List Methods
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
# Sort the list
numbers.sort()
print(numbers) # [1, 1, 2, 3, 4, 5, 6, 9]
# Reverse the list
numbers.reverse()
print(numbers) # [9, 6, 5, 4, 3, 2, 1, 1]
# Find index of element
print(numbers.index(5)) # 2
# Count occurrences
print(numbers.count(1)) # 2
# Get length
print(len(numbers)) # 8
Tuples¶
Tuples are ordered, immutable sequences.
Creating Tuples
# Empty tuple
empty_tuple = ()
# Tuple with elements
coordinates = (10, 20)
person = ("Alice", 25, "Engineer")
# Single element tuple (note the comma)
single = (5,)
Tuple Operations
coordinates = (10, 20, 30)
# Access elements
print(coordinates[0]) # 10
print(coordinates[-1]) # 30
# Slicing
print(coordinates[1:]) # (20, 30)
# Unpacking
x, y, z = coordinates
print(x, y, z) # 10 20 30
Dictionaries¶
Dictionaries store key-value pairs and are unordered.
Creating Dictionaries
# Empty dictionary
empty_dict = {}
# Dictionary with data
student = {
"name": "Alice",
"age": 20,
"grade": "A"
}
# Using dict() constructor
person = dict(name="Bob", age=25, city="New York")
Dictionary Operations
student = {"name": "Alice", "age": 20, "grade": "A"}
# Access values
print(student["name"]) # Alice
print(student.get("age")) # 20
# Add new key-value pair
student["major"] = "Computer Science"
print(student)
# Modify existing value
student["age"] = 21
print(student)
# Remove key-value pair
del student["grade"]
print(student)
# Check if key exists
print("name" in student) # True
# Get all keys
print(student.keys()) # dict_keys(['name', 'age', 'major'])
# Get all values
print(student.values()) # dict_values(['Alice', 21, 'Computer Science'])
# Get all key-value pairs
print(student.items()) # dict_items([('name', 'Alice'), ('age', 21), ('major', 'Computer Science')])
Dictionary Example: Student Records
students = {
"001": {"name": "Alice", "grade": "A"},
"002": {"name": "Bob", "grade": "B"},
"003": {"name": "Charlie", "grade": "A"}
}
# Access nested dictionary
print(students["001"]["name"]) # Alice
# Add new student
students["004"] = {"name": "David", "grade": "B"}
# Update grade
students["002"]["grade"] = "A"
Dictionary Example: Word Frequency Counter
text = "hello world hello python world"
words = text.split()
word_count = {}
for word in words:
if word in word_count:
word_count[word] += 1
else:
word_count[word] = 1
print(word_count) # {'hello': 2, 'world': 2, 'python': 1}
Sets¶
Sets are unordered collections of unique elements.
Creating Sets
# Empty set
empty_set = set()
# Set with elements
numbers = {1, 2, 3, 4, 5}
fruits = {"apple", "banana", "cherry"}
# From list (removes duplicates)
numbers = set([1, 2, 2, 3, 3, 3])
print(numbers) # {1, 2, 3}
Set Operations
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
# Add element
set1.add(5)
print(set1) # {1, 2, 3, 4, 5}
# Remove element
set1.remove(5)
print(set1) # {1, 2, 3, 4}
# Union
print(set1 | set2) # {1, 2, 3, 4, 5, 6}
# Intersection
print(set1 & set2) # {3, 4}
# Difference
print(set1 - set2) # {1, 2}
# Symmetric difference
print(set1 ^ set2) # {1, 2, 5, 6}
Data Structure Comparison¶
Advanced List Operations¶
List Comprehensions
# Create list of squares
squares = [x**2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# Filter even numbers
evens = [x for x in range(10) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8]
# Nested comprehensions
matrix = [[i*j for j in range(3)] for i in range(3)]
print(matrix) # [[0, 0, 0], [0, 1, 2], [0, 2, 4]]
List as Stack and Queue
# Stack (LIFO)
stack = []
stack.append(1) # Push
stack.append(2)
stack.append(3)
print(stack.pop()) # 3 (Pop)
# Queue (FIFO) - inefficient for large lists
queue = []
queue.append(1) # Enqueue
queue.append(2)
queue.append(3)
print(queue.pop(0)) # 1 (Dequeue)
Advanced Dictionary Operations¶
Dictionary Comprehensions
# Create dict of squares
squares = {x: x**2 for x in range(5)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# Filter dictionary
grades = {'Alice': 85, 'Bob': 92, 'Charlie': 78}
passed = {name: grade for name, grade in grades.items() if grade >= 80}
print(passed) # {'Alice': 85, 'Bob': 92}
Merging Dictionaries
dict1 = {'a': 1, 'b': 2}
dict2 = {'c': 3, 'd': 4}
# Python 3.9+
merged = dict1 | dict2
print(merged) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# Update method
dict1.update(dict2)
print(dict1) # {'a': 1, 'b': 2, 'c': 3, 'd': 4}
Default Values with defaultdict
from collections import defaultdict
# Default list
word_groups = defaultdict(list)
words = ['apple', 'banana', 'cherry', 'apricot']
for word in words:
word_groups[word[0]].append(word)
print(word_groups) # {'a': ['apple', 'apricot'], 'b': ['banana'], 'c': ['cherry']}
# Default counter
word_count = defaultdict(int)
text = "hello world hello python"
for word in text.split():
word_count[word] += 1
print(word_count) # defaultdict(<class 'int'>, {'hello': 2, 'world': 1, 'python': 1})
Advanced Set Operations¶
Set Comprehensions
# Create set of squares
squares = {x**2 for x in range(10)}
print(squares) # {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
# Filter unique even numbers
numbers = [1, 2, 2, 3, 4, 4, 5]
evens = {x for x in numbers if x % 2 == 0}
print(evens) # {2, 4}
Frozen Sets (Immutable Sets)
# Create frozen set
frozen = frozenset([1, 2, 3, 4])
print(frozen) # frozenset({1, 2, 3, 4})
# Can be used as dictionary keys
my_dict = {frozen: "value"}
print(my_dict[frozen]) # value
Common Data Structure Use Cases¶
Lists
Storing sequences of items
Implementing stacks and queues
Matrix operations
Dynamic arrays
Tuples
Returning multiple values from functions
Dictionary keys (immutable)
Unpacking assignments
Fixed configuration data
Dictionaries
Key-value data storage
Caching results
Counting frequencies
Configuration settings
Sets
Removing duplicates
Membership testing
Mathematical set operations
Finding unique elements
Performance Considerations¶
Time Complexity
Operation |
List |
Tuple |
Dict |
Set |
|---|---|---|---|---|
Access by index |
O(1) |
O(1) |
O(1) |
N/A |
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) |
Space Complexity
Lists: O(n)
Tuples: O(n)
Dictionaries: O(n)
Sets: O(n)
Tips
Use lists for ordered collections you need to modify
Use tuples for immutable sequences
Use dictionaries for fast lookups by key
Use sets for unique items and set operations
Consider collections.deque for efficient queue operations
Use collections.Counter for counting frequencies