🎉 75% of content is free forever — Unlock Premium from $10/mo →
CW
Search courses…
💼 Servicesℹ️ About✉️ ContactView Pricing Plansfrom $10

Python Lists — The Complete Guide to Python's Most Versatile Data Structure

Python BasicsLists🟢 Free Lesson

Advertisement

Python Lists — The Complete Guide

💡 Lists are the most widely used data structure in Python. This comprehensive guide covers everything from basic creation to advanced techniques, giving you complete mastery over Python's most versatile collection type.

Learning Objectives

By the end of this tutorial, you will be able to:

  • Create lists using various methods and understand when to use each
  • Use indexing and slicing to access and manipulate list elements
  • Apply all built-in list methods confidently
  • Use all related built-in functions: len(), min(), max(), sum(), sorted(), reversed(), enumerate(), zip(), map(), filter(), any(), all()
  • Write basic and intermediate list comprehensions
  • Understand nested lists and 2D data structures
  • Recognize performance implications of different operations
  • Avoid common pitfalls that trip up Python developers

What Are Lists?

A list is an ordered, mutable collection in Python. Think of it as a container that holds multiple items in a specific sequence.

mixed = [42, "hello", 3.14, True, None, [1, 2, 3]]
print(mixed)
# Output: [42, 'hello', 3.14, True, None, [1, 2, 3]]

Key Characteristics

CharacteristicDescriptionExample
OrderedElements maintain their insertion order[1, 2, 3] is different from [3, 2, 1]
MutableElements can be changed after creationlst[0] = 99 works fine
DynamicCan grow or shrink at runtimelst.append(4) adds an element
HeterogeneousCan mix different types[1, "two", 3.0] is valid
Duplicates allowedSame value can appear multiple times[1, 1, 2, 3] is valid
Zero-indexedFirst element is at index 0lst[0] gets the first item

Creating Lists

1. Literal Syntax (Most Common)

empty = []
fruits = ["apple", "banana", "cherry"]
numbers = [1, 2, 3, 4, 5]
mixed = [1, "two", 3.0, True]

2. The list() Constructor

chars = list("Python")        # ['P', 'y', 't', 'h', 'o', 'n']
numbers = list(range(1, 6))    # [1, 2, 3, 4, 5]
from_tuple = list((10, 20, 30))  # [10, 20, 30]

3. List Multiplication

zeros = [0] * 5         # [0, 0, 0, 0, 0]
pattern = [0, 1] * 4    # [0, 1, 0, 1, 0, 1, 0, 1]

# WARNING: Be careful with mutable objects
nested = [[0]] * 3
nested[0][0] = 99
print(nested)  # [[99], [99], [99]] — All sublists are the same object!

4. List Comprehension

squares = [x**2 for x in range(5)]
print(squares)  # [0, 1, 4, 9, 16]

evens = [x for x in range(10) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

Indexing and Slicing

fruits = ["apple", "banana", "cherry", "date", "elderberry"]
#           0        1        2        3         4

print(fruits[0])   # apple
print(fruits[2])   # cherry
print(fruits[-1])  # elderberry

# Slicing
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numbers[2:5])     # [2, 3, 4]
print(numbers[:4])      # [0, 1, 2, 3]
print(numbers[6:])      # [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]

Slice Assignment (Mutating Slices)

letters = ['a', 'b', 'c', 'd', 'e']
letters[1:3] = ['B', 'C', 'D']  # Replace 2 elements with 3
print(letters)  # ['a', 'B', 'C', 'D', 'd', 'e']

letters[1:1] = ['X', 'Y']  # Insert before index 1
print(letters)  # ['a', 'X', 'Y', 'B', 'C', 'D', 'd', 'e']

letters[2:5] = []  # Remove elements at indices 2, 3, 4
print(letters)  # ['a', 'X', 'B', 'd', 'e']

All List Methods

Adding Elements

MethodDescriptionTime Complexity
append(x)Add x to the endO(1) amortized
extend(iterable)Add all items from iterableO(k)
insert(i, x)Insert x at position iO(n)
# append() — adds a single element to the end
fruits = ["apple", "banana"]
fruits.append("cherry")
print(fruits)  # ['apple', 'banana', 'cherry']

# append a list as a single element
fruits.append(["date", "elderberry"])
print(fruits)  # ['apple', 'banana', 'cherry', ['date', 'elderberry']]

# extend() — adds multiple elements from an iterable
fruits = ["apple", "banana"]
fruits.extend(["cherry", "date"])
print(fruits)  # ['apple', 'banana', 'cherry', 'date']

# extend vs append
a = [1, 2]
a.extend([3, 4])  # Adds 3 and 4 as separate elements
print(a)  # [1, 2, 3, 4]

b = [1, 2]
b.append([3, 4])  # Adds [3, 4] as a single element
print(b)  # [1, 2, [3, 4]]

# insert() — adds element at a specific position
names = ["Alice", "Bob", "David"]
names.insert(2, "Charlie")  # Insert "Charlie" at index 2
print(names)  # ['Alice', 'Bob', 'Charlie', 'David']

names.insert(0, "Zara")  # Insert at the beginning
print(names)  # ['Zara', 'Alice', 'Bob', 'Charlie', 'David']

Removing Elements

MethodDescriptionTime Complexity
remove(x)Remove first occurrence of xO(n)
pop(i)Remove and return element at index iO(n) for i≠-1, O(1) for i=-1
del lst[i]Remove element at index iO(n)
clear()Remove all elementsO(n)
# remove() — removes first occurrence of a value
colors = ["red", "blue", "green", "blue"]
colors.remove("blue")
print(colors)  # ['red', 'green', 'blue']

# pop() — removes and returns element at index
stack = [10, 20, 30, 40, 50]
last = stack.pop()
print(last)   # 50
print(stack)  # [10, 20, 30, 40]

second = stack.pop(1)
print(second)  # 20

# del — keyword for removing elements
data = [10, 20, 30, 40, 50]
del data[2]       # Remove element at index 2
del data[1:3]     # Remove a slice
del data[:]       # Clear the list

# clear() — remove all elements
items = [1, 2, 3, 4, 5]
items.clear()
print(items)  # []

Searching

MethodDescriptionTime Complexity
index(x)Return index of first occurrence of xO(n)
count(x)Count occurrences of xO(n)
x in lstCheck if x is in the listO(n)
# index() — find position of an element
primes = [2, 3, 5, 7, 11, 13, 17]
print(primes.index(7))   # 3
print(primes.index(13))  # 5

# count() — how many times does a value appear?
data = [1, 2, 2, 3, 2, 4, 2]
print(data.count(2))  # 4
print(data.count(5))  # 0

# The 'in' operator
fruits = ["apple", "banana", "cherry"]
print("banana" in fruits)   # True
print("grape" in fruits)    # False

Sorting

Method/FunctionDescriptionReturns
lst.sort()Sort list in-placeNone
sorted(lst)Return new sorted listNew list
lst.sort(key=fn)Sort with custom keyNone
lst.sort(reverse=True)Sort descendingNone
reversed(lst)Return reverse iteratorIterator
lst.reverse()Reverse in-placeNone
# sort() — in-place sorting
scores = [85, 92, 78, 95, 88]
scores.sort()
print(scores)  # [78, 85, 88, 92, 95]

scores.sort(reverse=True)
print(scores)  # [95, 92, 88, 85, 78]

# sorted() — returns a new sorted list
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
new_sorted = sorted(numbers)
print(numbers)     # [3, 1, 4, 1, 5, 9, 2, 6] — unchanged
print(new_sorted)  # [1, 1, 2, 3, 4, 5, 6, 9]

# Sorting with a key function
words = ["banana", "apple", "cherry", "date"]
words.sort(key=len)  # Sort by string length
print(words)  # ['date', 'apple', 'banana', 'cherry']

# Case-insensitive sorting
names = ["charlie", "Alice", "bob"]
names.sort(key=str.lower)
print(names)  # ['Alice', 'bob', 'charlie']

# Sort by specific attribute
students = [("Alice", 85), ("Bob", 92), ("Charlie", 78)]
students.sort(key=lambda student: student[1])
print(students)  # [('Charlie', 78), ('Alice', 85), ('Bob', 92)]

# reversed() — returns an iterator
nums = [1, 2, 3]
rev = reversed(nums)
print(list(rev))  # [3, 2, 1]
print(nums)       # [1, 2, 3] — unchanged

# reverse() — in-place reversal
nums = [1, 2, 3]
nums.reverse()
print(nums)  # [3, 2, 1]

Other Methods

# copy() — create a shallow copy
original = [1, 2, 3, [4, 5]]
copied = original.copy()
copied[0] = 99
print(original)  # [1, 2, 3, [4, 5]] — unchanged

# But shallow copy has caveats with nested objects
copied[3][0] = 99
print(original)  # [1, 2, 3, [99, 5]] — nested list is shared!

Related Built-In Functions

len() — Number of Elements

numbers = [4, 2, 7, 1, 9, 3]
print(len(numbers))  # 6

words = ["apple", "banana", "cherry"]
print(len(words))    # 3

print(len([]))       # 0

min() and max() — Minimum and Maximum

numbers = [4, 2, 7, 1, 9, 3]
print(min(numbers))  # 1
print(max(numbers))  # 9

# With strings (lexicographic)
words = ["apple", "banana", "cherry"]
print(min(words))  # 'apple'
print(max(words))  # 'cherry'

# With key function
students = [("Alice", 85), ("Bob", 92), ("Charlie", 78)]
print(min(students, key=lambda s: s[1]))  # ('Charlie', 78)
print(max(students, key=lambda s: s[1]))  # ('Bob', 92)

sum() — Sum of Elements

numbers = [1, 2, 3, 4, 5]
print(sum(numbers))  # 15

# With start value
print(sum(numbers, 10))  # 25

# Sum of booleans (True=1, False=0)
booleans = [True, False, True, True, False]
print(sum(booleans))  # 3

sorted() — Return New Sorted List

numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print(sorted(numbers))  # [1, 1, 2, 3, 4, 5, 6, 9]

# With key
words = ["banana", "apple", "cherry"]
print(sorted(words, key=len))  # ['apple', 'banana', 'cherry']

# With reverse
print(sorted(numbers, reverse=True))  # [9, 6, 5, 4, 3, 2, 1, 1]

reversed() — Return Reverse Iterator

numbers = [1, 2, 3, 4, 5]
rev = reversed(numbers)
print(list(rev))  # [5, 4, 3, 2, 1]
print(numbers)    # [1, 2, 3, 4, 5] — unchanged

# Useful in for loops
for num in reversed([1, 2, 3, 4, 5]):
    print(num, end=" ")
# 5 4 3 2 1

enumerate() — Index and Value Pairs

fruits = ["apple", "banana", "cherry"]

for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")
# 0: apple
# 1: banana
# 2: cherry

# With custom start
for index, fruit in enumerate(fruits, start=1):
    print(f"{index}. {fruit}")
# 1. apple
# 2. banana
# 3. cherry

zip() — Combine Multiple Iterables

names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
grades = ["A", "A+", "B+"]

# Zip two lists
for name, score in zip(names, scores):
    print(f"{name}: {score}")

# Zip three lists
for name, score, grade in zip(names, scores, grades):
    print(f"{name}: {score} ({grade})")

# Convert to list of tuples
pairs = list(zip(names, scores))
print(pairs)  # [('Alice', 85), ('Bob', 92), ('Charlie', 78)]

map() — Apply Function to Each Element

numbers = [1, 2, 3, 4, 5]

# Square each number
squared = list(map(lambda x: x**2, numbers))
print(squared)  # [1, 4, 9, 16, 25]

# With multiple iterables
a = [1, 2, 3]
b = [10, 20, 30]
sums = list(map(lambda x, y: x + y, a, b))
print(sums)  # [11, 22, 33]

# Convert strings to integers
str_nums = ["1", "2", "3", "4", "5"]
int_nums = list(map(int, str_nums))
print(int_nums)  # [1, 2, 3, 4, 5]

filter() — Keep Elements Where Function Returns True

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Keep even numbers
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # [2, 4, 6, 8, 10]

# Keep strings longer than 3 characters
words = ["hi", "hello", "hey", "howdy", "yo"]
long_words = list(filter(lambda w: len(w) > 3, words))
print(long_words)  # ['hello', 'howdy']

# Filter out None values
data = [1, None, 2, None, 3]
clean = list(filter(None, data))
print(clean)  # [1, 2, 3]

any() and all() — Boolean Checks

numbers = [0, 1, 2, 3, 4]
print(any(numbers))  # True — at least one truthy value
print(all(numbers))  # False — not all truthy (0 is falsy)

numbers = [1, 2, 3, 4, 5]
print(all(numbers))  # True — all truthy

# With conditions
words = ["hello", "world", "python"]
print(all(len(w) > 3 for w in words))  # True
print(any(len(w) > 10 for w in words))  # False

# Check if any element meets condition
students = [("Alice", 85), ("Bob", 92), ("Charlie", 78)]
print(any(score >= 90 for _, score in students))  # True
print(all(score >= 90 for _, score in students))  # False

List Comprehensions

Basic Syntax

squares = [x**2 for x in range(10)]
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Filtering with Conditions

evens = [x for x in range(20) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

long_words = [word.upper() for word in ["hi", "hello", "hey", "howdy"] if len(word) > 2]
print(long_words)  # ['HELLO', 'HOWDY']

Nested Comprehensions

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
print(flat)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

identity = [[1 if i == j else 0 for j in range(3)] for i in range(3)]
print(identity)  # [[1, 0, 0], [0, 1, 0], [0, 0, 1]]

Conditional Expressions (Ternary)

labels = ["even" if x % 2 == 0 else "odd" for x in range(5)]
print(labels)  # ['even', 'odd', 'even', 'odd', 'even']

Nested Lists

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

print(matrix[0][0])  # 1
print(matrix[1][2])  # 6

# Matrix addition
A = [[1, 2], [3, 4]]
B = [[5, 6], [7, 8]]
C = [[A[i][j] + B[i][j] for j in range(2)] for i in range(2)]
print(C)  # [[6, 8], [10, 12]]

# Transpose
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = [[row[i] for row in matrix] for i in range(3)]
print(transposed)  # [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Deep Copy vs Shallow Copy

import copy

original = [[1, 2, 3], [4, 5, 6]]

# Shallow copy — nested objects are shared
shallow = original.copy()
shallow[0][0] = 99
print(original[0][0])  # 99 — original is affected!

# Deep copy — everything is copied
original = [[1, 2, 3], [4, 5, 6]]
deep = copy.deepcopy(original)
deep[0][0] = 99
print(original[0][0])  # 1 — original is safe

Lists vs Other Sequences

Lists vs Tuples

FeatureList []Tuple ()
MutableYesNo
Syntax[1, 2, 3](1, 2, 3)
PerformanceSlightly slowerSlightly faster
Use caseDynamic collectionsFixed records
Dictionary keyNoYes (if hashable)

Lists vs Generators

FeatureListGenerator
MemoryStores all elementsProduces on demand
IterationMultiple timesSingle pass
IndexingSupports lst[i]No random access
import sys

# List — all elements stored in memory
squares_list = [x**2 for x in range(1_000_000)]

# Generator — produces values on demand
squares_gen = (x**2 for x in range(1_000_000))

print(sys.getsizeof(squares_list))  # ~8,448,728 bytes
print(sys.getsizeof(squares_gen))   # ~208 bytes

Common Patterns

Unpacking

first, second, *rest = [1, 2, 3, 4, 5]
print(first)   # 1
print(rest)    # [3, 4, 5]

first, _, third, *_ = [1, 2, 3, 4, 5]
print(third)  # 3

# Unpacking in function arguments
def greet(name, age):
    return f"{name} is {age} years old"

person = ["Alice", 30]
print(greet(*person))  # "Alice is 30 years old"

Removing Duplicates (Preserving Order)

def remove_duplicates(lst):
    seen = set()
    result = []
    for item in lst:
        if item not in seen:
            seen.add(item)
            result.append(item)
    return result

data = [3, 1, 2, 3, 1, 4, 2, 5]
print(remove_duplicates(data))  # [3, 1, 2, 4, 5]

# Simpler approach (Python 3.7+)
unique = list(dict.fromkeys(data))
print(unique)  # [3, 1, 2, 4, 5]

Flattening Nested Lists

nested = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
flat = [item for sublist in nested for item in sublist]
print(flat)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

from itertools import chain
flat = list(chain.from_iterable(nested))
print(flat)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

Performance Considerations

OperationTime ComplexityNotes
append(x)O(1) amortizedFast
pop() (from end)O(1)Fast
pop(0) (from start)O(n)Slow — all elements shift
insert(0, x)O(n)Slow — all elements shift
x in lstO(n)Linear search
lst[i]O(1)Random access is fast
len(lst)O(1)Length is cached
sort()O(n log n)Timsort algorithm
copy()O(n)Must copy all elements

When to Use collections.deque

from collections import deque

# deque is optimized for append/popleft operations
dq = deque([1, 2, 3])
dq.appendleft(0)  # O(1) — fast regardless of size

# List — O(n) for insert at start
lst = [1, 2, 3]
lst.insert(0, 0)  # Slow for large lists

Common Mistakes

1. Mutable Default Arguments

# WRONG
def add_item(item, lst=[]):
    lst.append(item)
    return lst

print(add_item(1))  # [1]
print(add_item(2))  # [1, 2] — unexpected!

# CORRECT
def add_item(item, lst=None):
    if lst is None:
        lst = []
    lst.append(item)
    return lst

print(add_item(1))  # [1]
print(add_item(2))  # [2]

2. Modifying While Iterating

# WRONG
numbers = [1, 2, 3, 4, 5, 6]
for num in numbers:
    if num % 2 == 0:
        numbers.remove(num)

# CORRECT
numbers = [1, 2, 3, 4, 5, 6]
numbers = [num for num in numbers if num % 2 != 0]

3. == vs is for Lists

a = [1, 2, 3]
b = [1, 2, 3]
c = a

print(a == b)   # True — same values
print(a is b)   # False — different objects
print(a is c)   # True — same object

4. Forgetting sort() Returns None

numbers = [3, 1, 4, 1, 5]
result = numbers.sort()
print(result)  # None!

# Use sorted() to get a new list
sorted_numbers = sorted(numbers)

Practice Exercises

Exercise 1: Remove Duplicates

def remove_duplicates(lst):
    seen = set()
    result = []
    for item in lst:
        if item not in seen:
            seen.add(item)
            result.append(item)
    return result

print(remove_duplicates([1, 2, 2, 3, 4, 4, 5]))  # [1, 2, 3, 4, 5]
print(remove_duplicates(["a", "b", "a", "c", "b"]))  # ['a', 'b', 'c']

Exercise 2: Rotate a List

def rotate_right(lst, k):
    if not lst:
        return lst
    k = k % len(lst)
    return lst[-k:] + lst[:-k]

print(rotate_right([1, 2, 3, 4, 5], 2))  # [4, 5, 1, 2, 3]
print(rotate_right([1, 2, 3, 4, 5], 7))  # [4, 5, 1, 2, 3]

Exercise 3: Find Common Elements

def common_elements(lst1, lst2):
    return list(set(lst1) & set(lst2))

print(common_elements([1, 2, 3, 4, 5], [3, 4, 5, 6, 7]))  # [3, 4, 5]
print(common_elements(["a", "b", "c"], ["b", "c", "d"]))  # ['b', 'c']

Key Takeaways

  1. Lists are ordered, mutable, and can hold any data type — Python's most versatile collection
  2. Use literal syntax [] — faster and more Pythonic than list()
  3. append() vs extend() — append adds one element, extend adds multiple
  4. sort() modifies in-place, sorted() returns a new list — choose based on whether you need to preserve the original
  5. List comprehensions are concise and fast — use them for simple transformations and filters
  6. Watch out for shallow copies with nested lists — use copy.deepcopy() when needed
  7. Avoid mutable default arguments — always use None as the default
  8. Consider performanceinsert(0, x) is O(n), use deque for frequent start insertions
  9. Use in for membership testing — but remember it's O(n) for lists
  10. Built-in functions like len(), min(), max(), sum(), sorted(), enumerate(), zip(), map(), filter(), any(), all() make list operations elegant and efficient

Premium Content

Python Lists — The Complete Guide to Python's Most Versatile Data Structure

Unlock this lesson and 900+ advanced tutorials with a Premium plan.

🎯End-to-end Projects
💼Interview Prep
📜Certificates
🤝Community Access

Already a member? Log in

Need Expert Python Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement