Python Lists¶
Table of Contents¶
- What are Lists?
- Creating Lists
- Accessing Elements
- Modifying Lists
- List Methods
- List Slicing
- List Comprehensions
- Common Operations
- Practical Examples
- Best Practices
1. What are Lists?¶
Lists are one of Python's most versatile data structures. They are:
- Ordered: Elements have a defined sequence
- Mutable: Can be changed after creation
- Allow duplicates: Same values can appear multiple times
- Mixed data types: Can store different types of data
In [ ]:
# Examples of what lists can store
mixed_list = [1, "hello", 3.14, True, [1, 2, 3]]
print(f"Mixed list: {mixed_list}")
print(f"Type: {type(mixed_list)}")
In [ ]:
# Method 1: Square brackets
empty_list1 = []
# Method 2: list() constructor
empty_list2 = list()
print(f"Empty list 1: {empty_list1}")
print(f"Empty list 2: {empty_list2}")
Lists with Initial Values¶
In [ ]:
# Numbers
numbers = [1, 2, 3, 4, 5]
# Strings
fruits = ["apple", "banana", "cherry"]
# Mixed types
mixed = [1, "two", 3.0, True]
# Nested lists
nested = [[1, 2], [3, 4], [5, 6]]
print(f"Numbers: {numbers}")
print(f"Fruits: {fruits}")
print(f"Mixed: {mixed}")
print(f"Nested: {nested}")
Creating Lists with Patterns¶
In [ ]:
# Repeat elements
zeros = [0] * 5
print(f"Zeros: {zeros}")
# Range to list
range_list = list(range(1, 6))
print(f"Range list: {range_list}")
# Even numbers
evens = list(range(0, 11, 2))
print(f"Even numbers: {evens}")
In [ ]:
fruits = ["apple", "banana", "cherry", "date"]
print(f"First fruit: {fruits[0]}")
print(f"Second fruit: {fruits[1]}")
print(f"Last fruit: {fruits[3]}")
Negative Indexing¶
In [ ]:
print(f"Last fruit: {fruits[-1]}")
print(f"Second to last: {fruits[-2]}")
print(f"First fruit (negative): {fruits[-4]}")
Index Visualization¶
In [ ]:
# Visual representation
fruits = ["apple", "banana", "cherry", "date"]
print("Positive indices: 0 1 2 3")
print("List contents: apple banana cherry date")
print("Negative indices: -4 -3 -2 -1")
Handling Index Errors¶
In [ ]:
try:
print(fruits[10]) # This will cause an error
except IndexError as e:
print(f"Error: {e}")
In [ ]:
numbers = [1, 2, 3, 4, 5]
print(f"Original: {numbers}")
numbers[0] = 10
numbers[-1] = 50
print(f"Modified: {numbers}")
Adding Elements¶
In [ ]:
fruits = ["apple", "banana"]
print(f"Original: {fruits}")
# append() - adds to end
fruits.append("cherry")
print(f"After append: {fruits}")
# insert() - adds at specific position
fruits.insert(1, "orange")
print(f"After insert: {fruits}")
# extend() - adds multiple elements
fruits.extend(["grape", "kiwi"])
print(f"After extend: {fruits}")
Removing Elements¶
In [ ]:
numbers = [1, 2, 3, 2, 4, 2, 5]
print(f"Original: {numbers}")
# remove() - removes first occurrence
numbers.remove(2)
print(f"After remove(2): {numbers}")
# pop() - removes and returns element
popped = numbers.pop() # removes last
print(f"Popped: {popped}, List: {numbers}")
popped_index = numbers.pop(1) # removes at index
print(f"Popped at index 1: {popped_index}, List: {numbers}")
# del - removes by index or slice
del numbers[0]
print(f"After del numbers[0]: {numbers}")
# clear() - removes all elements
copy_numbers = numbers.copy()
copy_numbers.clear()
print(f"After clear(): {copy_numbers}")
In [ ]:
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
fruits = ["banana", "apple", "cherry"]
print(f"Original numbers: {numbers}")
print(f"Original fruits: {fruits}")
# count() - count occurrences
print(f"Count of 1: {numbers.count(1)}")
# index() - find first index
print(f"Index of 4: {numbers.index(4)}")
# sort() - sort in place
numbers.sort()
print(f"Sorted numbers: {numbers}")
fruits.sort()
print(f"Sorted fruits: {fruits}")
# reverse() - reverse in place
numbers.reverse()
print(f"Reversed numbers: {numbers}")
# copy() - create a shallow copy
numbers_copy = numbers.copy()
print(f"Copy: {numbers_copy}")
Advanced Sorting¶
In [ ]:
words = ["banana", "apple", "Cherry", "date"]
numbers = [3, -1, 4, -2, 5]
print(f"Original words: {words}")
print(f"Original numbers: {numbers}")
# Case-insensitive sort
words_sorted = sorted(words, key=str.lower)
print(f"Case-insensitive sort: {words_sorted}")
# Sort by absolute value
numbers_abs_sorted = sorted(numbers, key=abs)
print(f"Sort by absolute value: {numbers_abs_sorted}")
# Reverse sort
numbers_desc = sorted(numbers, reverse=True)
print(f"Descending order: {numbers_desc}")
In [ ]:
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(f"Original: {numbers}")
# Basic slicing: [start:end]
print(f"numbers[2:5]: {numbers[2:5]}")
print(f"numbers[:4]: {numbers[:4]}")
print(f"numbers[6:]: {numbers[6:]}")
print(f"numbers[:]: {numbers[:]}") # full copy
Step in Slicing¶
In [ ]:
# With step: [start:end:step]
print(f"Every 2nd element: {numbers[::2]}")
print(f"Every 2nd from index 1: {numbers[1::2]}")
print(f"Reverse: {numbers[::-1]}")
print(f"Every 3rd reversed: {numbers[::-3]}")
Negative Indices in Slicing¶
In [ ]:
print(f"Last 3 elements: {numbers[-3:]}")
print(f"All except last 2: {numbers[:-2]}")
print(f"From 3rd last to 2nd: {numbers[-3:-1]}")
Modifying with Slicing¶
In [ ]:
numbers = [0, 1, 2, 3, 4, 5]
print(f"Original: {numbers}")
# Replace a slice
numbers[1:4] = [10, 20, 30]
print(f"After slice replacement: {numbers}")
# Insert elements
numbers[2:2] = [15, 25]
print(f"After insertion: {numbers}")
# Delete elements
del numbers[1:3]
print(f"After deletion: {numbers}")
In [ ]:
# Traditional way
squares_traditional = []
for i in range(1, 6):
squares_traditional.append(i**2)
print(f"Traditional way: {squares_traditional}")
# List comprehension way
squares_comprehension = [i**2 for i in range(1, 6)]
print(f"List comprehension: {squares_comprehension}")
List Comprehensions with Conditions¶
In [ ]:
# Even numbers
evens = [x for x in range(1, 11) if x % 2 == 0]
print(f"Even numbers: {evens}")
# String manipulation
words = ["hello", "world", "python", "programming"]
upper_words = [word.upper() for word in words if len(word) > 5]
print(f"Long words (uppercase): {upper_words}")
Complex List Comprehensions¶
In [ ]:
# Nested loops
matrix = [[i*j for i in range(1, 4)] for j in range(1, 4)]
print("Matrix:")
for row in matrix:
print(row)
# Flattening a matrix
flat = [num for row in matrix for num in row]
print(f"Flattened: {flat}")
# Conditional expressions
numbers = range(-5, 6)
abs_or_zero = [x if x >= 0 else 0 for x in numbers]
print(f"Absolute or zero: {abs_or_zero}")
In [ ]:
fruits = ["apple", "banana", "cherry"]
print(f"'apple' in fruits: {'apple' in fruits}")
print(f"'orange' in fruits: {'orange' in fruits}")
print(f"'grape' not in fruits: {'grape' not in fruits}")
Length and Boolean Evaluation¶
In [ ]:
empty_list = []
filled_list = [1, 2, 3]
print(f"Length of empty list: {len(empty_list)}")
print(f"Length of filled list: {len(filled_list)}")
print(f"Boolean value of empty list: {bool(empty_list)}")
print(f"Boolean value of filled list: {bool(filled_list)}")
List Concatenation and Repetition¶
In [ ]:
list1 = [1, 2, 3]
list2 = [4, 5, 6]
# Concatenation
combined = list1 + list2
print(f"Combined: {combined}")
# Repetition
repeated = list1 * 3
print(f"Repeated: {repeated}")
# In-place concatenation
list1 += list2
print(f"list1 after +=: {list1}")
Min, Max, and Sum¶
In [ ]:
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print(f"Numbers: {numbers}")
print(f"Min: {min(numbers)}")
print(f"Max: {max(numbers)}")
print(f"Sum: {sum(numbers)}")
print(f"Average: {sum(numbers) / len(numbers):.2f}")
In [ ]:
# Student grade management
students = ["Alice", "Bob", "Charlie", "Diana"]
grades = [85, 92, 78, 96]
print("Student Grades:")
for i in range(len(students)):
print(f"{students[i]}: {grades[i]}")
# Find top performer
top_score = max(grades)
top_student_index = grades.index(top_score)
print(f"\nTop performer: {students[top_student_index]} with {top_score}")
# Calculate class average
average = sum(grades) / len(grades)
print(f"Class average: {average:.2f}")
# Students above average
above_average = []
for i, grade in enumerate(grades):
if grade > average:
above_average.append(students[i])
print(f"Students above average: {above_average}")
Example 2: Shopping Cart¶
In [ ]:
# Shopping cart implementation
cart = []
def add_item(item, quantity=1):
for _ in range(quantity):
cart.append(item)
print(f"Added {quantity} {item}(s) to cart")
def remove_item(item):
if item in cart:
cart.remove(item)
print(f"Removed {item} from cart")
else:
print(f"{item} not found in cart")
def show_cart():
if cart:
print("Shopping Cart:")
unique_items = list(set(cart))
for item in unique_items:
count = cart.count(item)
print(f" {item}: {count}")
else:
print("Cart is empty")
# Simulate shopping
add_item("apple", 3)
add_item("banana", 2)
add_item("apple", 1)
show_cart()
remove_item("banana")
show_cart()
Example 3: Data Processing¶
In [ ]:
# Temperature data processing
temperatures = [23.5, 25.0, 22.8, 26.2, 24.1, 21.9, 27.3, 25.8]
print(f"Temperature data: {temperatures}")
# Basic statistics
print(f"Average temperature: {sum(temperatures) / len(temperatures):.2f}°C")
print(f"Highest temperature: {max(temperatures)}°C")
print(f"Lowest temperature: {min(temperatures)}°C")
# Filter temperatures above average
avg_temp = sum(temperatures) / len(temperatures)
above_avg = [temp for temp in temperatures if temp > avg_temp]
print(f"Temperatures above average: {above_avg}")
# Convert to Fahrenheit
fahrenheit = [(temp * 9/5) + 32 for temp in temperatures]
print(f"Temperatures in Fahrenheit: {[f'{temp:.1f}°F' for temp in fahrenheit]}")
In [ ]:
# ✅ Good: Use list comprehension for simple operations
squares = [x**2 for x in range(10)]
# ❌ Avoid: Unnecessary loops
squares_slow = []
for x in range(10):
squares_slow.append(x**2)
# ✅ Good: Use extend() to add multiple items
my_list = [1, 2, 3]
my_list.extend([4, 5, 6])
# ❌ Avoid: Multiple append() calls
my_list_slow = [1, 2, 3]
my_list_slow.append(4)
my_list_slow.append(5)
my_list_slow.append(6)
Memory and Copying¶
In [ ]:
# Shallow vs Deep copy
import copy
original = [[1, 2], [3, 4]]
shallow = original.copy() # or original[:]
deep = copy.deepcopy(original)
print(f"Original: {original}")
original[0][0] = 99
print(f"After modifying original[0][0]:")
print(f"Original: {original}")
print(f"Shallow copy: {shallow}") # Also changed!
print(f"Deep copy: {deep}") # Unchanged
Common Pitfalls to Avoid¶
In [ ]:
# ❌ Pitfall 1: Modifying list while iterating
numbers = [1, 2, 3, 4, 5]
# Don't do this:
# for i, num in enumerate(numbers):
# if num % 2 == 0:
# numbers.pop(i) # This can cause issues
# ✅ Better approach:
numbers = [num for num in numbers if num % 2 != 0]
print(f"Odd numbers only: {numbers}")
# ❌ Pitfall 2: Default mutable arguments
def add_item_bad(item, target_list=[]): # Don't do this
target_list.append(item)
return target_list
# ✅ Better approach:
def add_item_good(item, target_list=None):
if target_list is None:
target_list = []
target_list.append(item)
return target_list