24, W Canal Bank Rd, Kotturpuram, Chennai, TN, India, 600085

info@vidhai.academy

Python Lists

Comprehensive Course Material

Introduction to Lists

A list in Python is an ordered, mutable collection of items. Lists are one of the most versatile and commonly used data structures in Python, allowing you to store multiple items in a single variable.

# Creating a simple list
fruits = ["apple", "banana", "cherry"]
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]

Creating Lists

There are several ways to create lists in Python:

# Empty list
empty_list = []
also_empty = list()

# List with initial values
colors = ["red", "green", "blue"]

# Using list() constructor
letters = list("hello")  # ['h', 'e', 'l', 'l', 'o']

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

Accessing List Elements

Indexing

Python uses zero-based indexing, meaning the first element is at index 0.

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

print(fruits[0])   # "apple"
print(fruits[2])   # "cherry"
print(fruits[-1])  # "date" (last element)
print(fruits[-2])  # "cherry" (second from end)

Slicing

You can extract portions of a list using slice notation: list[start:stop:step]

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

print(numbers[2:5])    # [2, 3, 4] (index 2 to 4)
print(numbers[:4])     # [0, 1, 2, 3] (start to index 3)
print(numbers[6:])     # [6, 7, 8, 9] (index 6 to end)
print(numbers[::2])    # [0, 2, 4, 6, 8] (every 2nd element)
print(numbers[::-1])   # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (reversed)

Modifying Lists

Changing Elements

fruits = ["apple", "banana", "cherry"]
fruits[1] = "blueberry"
print(fruits)  # ["apple", "blueberry", "cherry"]

Adding Elements

# append() - adds to the end
fruits = ["apple", "banana"]
fruits.append("cherry")
print(fruits)  # ["apple", "banana", "cherry"]

# insert() - adds at specific position
fruits.insert(1, "blueberry")
print(fruits)  # ["apple", "blueberry", "banana", "cherry"]

# extend() - adds multiple elements
fruits.extend(["date", "elderberry"])

# Using + operator
more_fruits = fruits + ["fig", "grape"]

Removing Elements

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

# remove() - removes first occurrence of value
fruits.remove("banana")

# pop() - removes and returns element at index
last_fruit = fruits.pop()  # removes last element
first_fruit = fruits.pop(0)  # removes first element

# del - removes element(s)
del fruits[1]  # removes element at index 1
del fruits[1:3]  # removes slice

# clear() - removes all elements
fruits.clear()
print(fruits)  # []

Common List Operations

Length, Min, Max, Sum

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

print(len(numbers))  # 8
print(min(numbers))  # 1
print(max(numbers))  # 9
print(sum(numbers))  # 31

Checking Membership

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

print("apple" in fruits)      # True
print("grape" in fruits)      # False
print("grape" not in fruits)  # True

Sorting

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

# sort() - modifies the list in place
numbers.sort()
print(numbers)  # [1, 1, 2, 3, 4, 5, 6, 9]

# sort in reverse
numbers.sort(reverse=True)

# sorted() - returns new sorted list
original = [3, 1, 4, 1, 5]
sorted_list = sorted(original)
print(original)      # [3, 1, 4, 1, 5] (unchanged)
print(sorted_list)   # [1, 1, 3, 4, 5]

Reversing

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

# reverse() - modifies list in place
fruits.reverse()
print(fruits)  # ["cherry", "banana", "apple"]

# reversed() - returns iterator
reversed_fruits = list(reversed(fruits))

Counting and Finding

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

# count() - counts occurrences
print(numbers.count(2))  # 3

# index() - finds first occurrence
print(numbers.index(2))  # 1
print(numbers.index(2, 2))  # 3 (start searching from index 2)

Iterating Over Lists

Basic Loop

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

for fruit in fruits:
    print(fruit)

With Index

# Using enumerate()
for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")

# Output:
# 0: apple
# 1: banana
# 2: cherry

While Loop

fruits = ["apple", "banana", "cherry"]
i = 0
while i < len(fruits):
    print(fruits[i])
    i += 1

List Comprehensions

List comprehensions provide a concise way to create lists based on existing lists or other iterables.

Basic Syntax

# Traditional approach
squares = []
for x in range(10):
    squares.append(x**2)

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

With Conditions

# Only even numbers
evens = [x for x in range(20) if x % 2 == 0]

# Uppercase only for words starting with 'a'
fruits = ["apple", "banana", "apricot", "cherry"]
a_fruits = [f.upper() for f in fruits if f.startswith('a')]
print(a_fruits)  # ['APPLE', 'APRICOT']

Nested List Comprehensions

# Create a 3x3 matrix
matrix = [[i + j for j in range(3)] for i in range(3)]
print(matrix)  # [[0, 1, 2], [1, 2, 3], [2, 3, 4]]

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

Nested Lists

Lists can contain other lists, creating multidimensional structures.

# 2D list (matrix)
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

# Accessing elements
print(matrix[0][0])  # 1
print(matrix[1][2])  # 6
print(matrix[2][1])  # 8

# Iterating through 2D list
for row in matrix:
    for element in row:
        print(element, end=' ')
    print()  # New line after each row

Copying Lists

Shallow Copy

# Using slice
original = [1, 2, 3]
copy1 = original[:]

# Using copy()
copy2 = original.copy()

# Using list()
copy3 = list(original)

# Problem with nested lists (shallow copy)
original = [[1, 2], [3, 4]]
shallow = original.copy()
shallow[0][0] = 999
print(original)  # [[999, 2], [3, 4]] - original is affected!

Deep Copy

import copy

original = [[1, 2], [3, 4]]
deep = copy.deepcopy(original)
deep[0][0] = 999
print(original)  # [[1, 2], [3, 4]] - original is unaffected
print(deep)      # [[999, 2], [3, 4]]

Advanced List Operations

Unpacking

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

# Basic unpacking
a, b, c = fruits
print(a)  # "apple"

# Using * for remaining elements
first, *rest = fruits
print(first)  # "apple"
print(rest)   # ["banana", "cherry"]

first, *middle, last = [1, 2, 3, 4, 5]
print(middle)  # [2, 3, 4]

Zip Function

names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
cities = ["New York", "London", "Paris"]

# Combine multiple lists
combined = list(zip(names, ages, cities))
print(combined)
# [('Alice', 25, 'New York'), ('Bob', 30, 'London'), ('Charlie', 35, 'Paris')]

# Unzip
names2, ages2, cities2 = zip(*combined)

Map and Filter

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

# Map - apply function to each element
squared = list(map(lambda x: x**2, numbers))
print(squared)  # [1, 4, 9, 16, 25]

# Filter - keep elements that satisfy condition
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # [2, 4]

Common Patterns and Best Practices

Finding Maximum/Minimum with Conditions

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

# Maximum absolute value
max_abs = max(numbers, key=abs)
print(max_abs)  # 9

# Longest string
words = ["cat", "elephant", "dog"]
longest = max(words, key=len)
print(longest)  # "elephant"

List as Stack (LIFO)

stack = []
stack.append(1)  # Push
stack.append(2)
stack.append(3)
print(stack.pop())  # 3 (Pop)
print(stack.pop())  # 2

List as Queue (FIFO) - Not Recommended

Note: For queue operations, it's better to use collections.deque instead of lists for better performance.
# Better to use collections.deque for queues
from collections import deque

queue = deque([1, 2, 3])
queue.append(4)  # Add to right
print(queue.popleft())  # Remove from left: 1

Practice Exercises

Exercises to Try

  1. Sum of Even Numbers: Write a function that returns the sum of all even numbers in a list.
  2. Remove Duplicates: Create a function that removes duplicates from a list while preserving order.
  3. Flatten Nested List: Write a function to flatten a nested list of arbitrary depth.
  4. Find Common Elements: Given two lists, find elements that appear in both.
  5. Rotate List: Rotate a list to the right by k positions.

Summary

Python lists are powerful and flexible data structures that support a wide range of operations including adding, removing, sorting, and searching elements. Understanding lists is fundamental to Python programming, and mastering list comprehensions can make your code more concise and Pythonic.

Remember that lists are mutable, which means they can be changed after creation, and this has implications for copying and passing lists to functions.

Python Lists Course Material | Happy Learning!

Python
Commercial Plumbing
Emergency Servicing