Python tutorials  /  Python Arrays (Lists) - Complete Guide with Examples
Chapter 8 · Python

Python Arrays (Lists) - Complete Guide with Examples

An array in Python is an ordered, mutable collection used to store multiple items in a single variable. While Python does not have a traditional 'array' type built into the core language for general use, the 'list' data type serves this purpose for most everyday programming, and the dedicated 'array' module or third-party libraries like NumPy provide true fixed-type arrays for numeric-heavy work.

Think of an array like a row of numbered lockers in a school hallway. Each locker holds one item, and every locker has a specific position number (index) starting from 0. You can open any locker directly by its number to see, change, or remove what's inside, without having to search through every other locker first.

Consider CompileX's online judge platform where thousands of students submit code every minute. The platform needs to store the list of currently online users to display a 'Live Coders' counter on the homepage. Developers use a Python list called 'online_users' to store usernames as they log in and remove them as they log out. Because lists preserve order and allow fast indexing, the platform can easily show the 5 most recently joined users by simply slicing the last 5 elements of the list, without writing complex database queries for a feature that updates every second.

Arrays (lists) are essential because they let programmers store and manage related pieces of data together under one variable name, rather than creating separate variables for each item. This enables efficient looping, sorting, searching, and bulk operations on data, which is fundamental for tasks like processing user records, storing scores, managing inventories, or handling any collection of similar items in a program.

  • Python List (Dynamic Array): The most commonly used array-like structure in Python, created using square brackets []. It is mutable, dynamically resizable, and can hold elements of different data types within the same list.
  • array Module Array: A more memory-efficient, type-restricted array provided by Python's built-in 'array' module, where all elements must be of the same specified data type (like integers or floats), imported using 'from array import array'.
  • NumPy Array (ndarray): A powerful, high-performance array structure from the third-party NumPy library, widely used in data science and scientific computing, supporting multi-dimensional arrays and fast vectorized mathematical operations.
  • Tuple (Immutable Array-like Sequence): A sequence type similar to a list but immutable, meaning its elements cannot be changed after creation, created using parentheses (), often used for fixed collections of data that should not be modified.
# Creating a list (array) my_list = [element1, element2, element3] # Accessing elements by index my_list[0] # Slicing my_list[start:end] # Common operations my_list.append(item) my_list.insert(index, item) my_list.remove(item) my_list.pop(index) len(my_list)
Imagine you are building a quiz application for CompileX where you need to store the scores of 50 participants and then find the top 3 scorers, calculate the average score, and identify how many students scored above 80. Creating 50 separate variables like score1, score2, ..., score50 would be unmanageable and impossible to loop through efficiently. How do you store all these related values in a single, organized structure that allows easy access, iteration, and bulk calculations?
Creating and Accessing a List
A basic example showing how to create a list of student scores and access individual elements using indexing.
Python
scores = [85, 92, 78, 95, 88] print(scores[0]) print(scores[-1]) print(scores[1:4])
85 88 [92, 78, 95]
scores[0] accesses the first element using zero-based indexing. scores[-1] accesses the last element using negative indexing. scores[1:4] slices the list from index 1 up to (but not including) index 4, returning a new sub-list.
Common List Methods: append, insert, remove
Demonstrates how to add and remove elements from a list dynamically, simulating an online users list.
Python
online_users = ["Aditi", "Rohan", "Meera"] online_users.append("Karan") print(online_users) online_users.insert(1, "Priya") print(online_users) online_users.remove("Rohan") print(online_users)
['Aditi', 'Rohan', 'Meera', 'Karan'] ['Aditi', 'Priya', 'Rohan', 'Meera', 'Karan'] ['Aditi', 'Priya', 'Meera', 'Karan']
append() adds an item to the end of the list. insert(index, item) adds an item at a specific position, shifting subsequent elements to the right. remove(item) deletes the first matching occurrence of that value from the list.
Iterating and Calculating with a List
Shows how to loop through a list of scores to calculate the average and count how many scores exceed a threshold, solving the quiz application problem.
Python
scores = [85, 92, 78, 95, 88, 65, 72] total = 0 above_80_count = 0 for score in scores: total += score if score > 80: above_80_count += 1 average = total / len(scores) print(f"Average Score: {average:.2f}") print(f"Students above 80: {above_80_count}")
Average Score: 82.14 Students above 80: 4
The for loop iterates over every score in the list, accumulating the total and counting how many scores exceed 80. The average is calculated by dividing the total by the number of elements using len(scores).
Using List Comprehension to Filter and Sort
Demonstrates a Pythonic way to filter top scorers and sort them, finding the top 3 scores using slicing after sorting.
Python
scores = [85, 92, 78, 95, 88, 65, 72] top_scores = sorted(scores, reverse=True)[:3] above_80 = [s for s in scores if s > 80] print(f"Top 3 Scores: {top_scores}") print(f"Scores above 80: {above_80}")
Top 3 Scores: [95, 92, 88] Scores above 80: [85, 92, 95, 88]
sorted(scores, reverse=True) creates a new list sorted in descending order, and [:3] slices the top 3 highest values. The list comprehension '[s for s in scores if s > 80]' builds a new list containing only scores greater than 80 in a single, concise line.
  • Confusing Index Position with Value: Beginners often confuse the index (position) of an element with its actual value, especially when the list contains numbers. For example, assuming scores[3] returns the 3rd score when it actually returns the 4th element (index 0 is the first), leading to off-by-one errors in calculations or reports.
  • IndexError from Accessing Out-of-Range Indices: Trying to access an index that doesn't exist in the list, such as my_list[10] on a list with only 5 elements, raises an IndexError and crashes the program. This commonly happens in loops when the loop range is not properly matched to the list's actual length.
  • Modifying a List While Iterating Over It: Removing or adding elements to a list while looping through it with a for loop causes elements to be skipped or unexpected behavior, because the list's indices shift as items are removed. The safe approach is to iterate over a copy of the list (using list[:] or list()) or build a new filtered list instead.
  • Assuming Lists Are Copied by Value: Writing 'list_b = list_a' does not create a new independent list; it only creates another reference pointing to the same list object in memory. Modifying list_b will also change list_a unexpectedly. To create a true independent copy, developers should use list_a.copy() or list(list_a).
  • Using Lists When a Set or Dictionary Would Be More Efficient: Using 'if item in my_list' to repeatedly check membership in a large list results in slow, linear-time search operations. When frequent membership checks are needed, converting the list to a set (which offers average constant-time lookups) significantly improves performance.
  • Use List Comprehensions for Concise, Readable Transformations: Instead of writing multi-line for loops to build a new list by filtering or transforming an existing one, use list comprehensions like '[x*2 for x in numbers if x > 0]' for cleaner, more Pythonic, and often faster code.
  • Prefer copy() or Slicing to Avoid Unintended Reference Sharing: When you need an independent duplicate of a list, always use 'new_list = original_list.copy()' or 'new_list = original_list[:]' instead of direct assignment, to prevent accidental modification of the original data.
  • Use enumerate() Instead of Manual Index Tracking: When you need both the index and value while looping through a list, use 'for index, value in enumerate(my_list):' instead of manually maintaining a separate counter variable, which reduces the chance of off-by-one errors.
  • Choose the Right Data Structure for the Task: Use a list when order and duplicates matter, a set when you need fast membership checks and unique values, and a dictionary when you need key-value pair lookups. Choosing the appropriate structure improves both performance and code clarity.
  • Use Meaningful, Plural Names for List Variables: Name list variables in plural form that clearly describe their contents, such as 'student_scores' or 'online_users', instead of vague names like 'data' or 'lst', to make the code self-explanatory to other developers.
What is the difference between a list and a tuple in Python?
A list is mutable, meaning its elements can be changed, added, or removed after creation, and is defined using square brackets []. A tuple is immutable, meaning once created, its elements cannot be modified, and is defined using parentheses (). Tuples are generally faster and used for fixed collections of data, while lists are used when the collection needs to change over time.
How do negative indices work in Python lists?
Negative indices allow access to elements from the end of the list, where -1 refers to the last element, -2 refers to the second-to-last element, and so on. This is useful for accessing recent items without needing to know the exact length of the list.
What is the time complexity of common list operations like append, insert, and searching for an element?
append() has an average time complexity of O(1) because it adds to the end of the underlying dynamic array. insert() at the beginning or middle has O(n) complexity because subsequent elements must be shifted. Searching for an element using 'in' or index() has O(n) complexity because it may need to check every element in the worst case.
What is the difference between shallow copy and deep copy when working with lists, especially nested lists?
A shallow copy (created using .copy() or list()) creates a new outer list, but if the list contains nested mutable objects like other lists, those inner objects are still shared by reference between the original and the copy. A deep copy (created using copy.deepcopy()) recursively copies all nested objects as well, creating a fully independent structure where changes to the copy never affect the original, even at nested levels.
Why does modifying a list while iterating over it with a for loop lead to unexpected behavior, and how can it be avoided?
When elements are removed or added during iteration, the list's internal indices shift, but the loop's internal position counter does not account for this shift, causing elements to be skipped or processed incorrectly. This can be avoided by iterating over a copy of the list (using 'for item in my_list[:]:'), or by building a new list with the desired elements instead of modifying the original list in place.
Write a function 'reverse_list' that takes a list as input and returns a new list with the elements in reverse order without using the built-in reverse() method or [::-1] slicing.
def reverse_list(lst): reversed_lst = [] for item in lst: reversed_lst.insert(0, item) return reversed_lst print(reverse_list([1, 2, 3, 4])) # [4, 3, 2, 1]
Write a function 'find_duplicates' that takes a list of numbers and returns a list of all values that appear more than once.
def find_duplicates(lst): seen = set() duplicates = set() for item in lst: if item in seen: duplicates.add(item) else: seen.add(item) return list(duplicates) print(find_duplicates([1, 2, 3, 2, 4, 1, 5])) # [1, 2]
Write a function 'merge_sorted_lists' that takes two already-sorted lists and merges them into a single sorted list without using the built-in sort() or sorted() functions.
def merge_sorted_lists(list1, list2): merged = [] i, j = 0, 0 while i < len(list1) and j < len(list2): if list1[i] <= list2[j]: merged.append(list1[i]) i += 1 else: merged.append(list2[j]) j += 1 merged.extend(list1[i:]) merged.extend(list2[j:]) return merged print(merge_sorted_lists([1, 3, 5], [2, 4, 6])) # [1, 2, 3, 4, 5, 6]

Python lists (commonly referred to as arrays) are ordered, mutable collections that allow developers to store, access, and manipulate multiple related values under a single variable name. They support powerful built-in methods for adding, removing, slicing, and transforming data, and are foundational to almost every real-world Python program, from web applications to data analysis pipelines. Understanding indexing, list comprehensions, and the pitfalls of reference sharing is essential for writing efficient and bug-free Python code.

© 2026 CompileX. Maintained by Aditya Kumar Sharma.