Python Arrays
Arrays in Python are data structures that store multiple values of the same type in a single variable.
While Python has several array-like structures, the most commonly used are:
- Lists (most versatile)
- array module arrays (for homogeneous numeric data)
- NumPy arrays (for advanced numerical computing)
Basic List Example :
fruits = ["apple", "banana", "cherry"]
Basic Array Operations
Creating Arrays :
# Using square brackets
numbers = [1, 2, 3, 4, 5]
# Using list() constructor
empty_list = list()
another_list = list((1, 2, 3)) # Note the double parentheses
# Using array module
import array
int_array = array.array('i', [1, 2, 3]) # 'i' for signed integers
Accessing Elements :
fruits = ["apple", "banana", "cherry"]
print(fruits[0]) # Accessing the first element
print(fruits[1]) # Accessing the second element
print(fruits[-1]) # Accessing the last element
Modifying Arrays :
# Changing elements
my_array[1] = 25 # [10, 25, 30, 40, 50]
# Adding elements
my_array.append(60) # [10, 25, 30, 40, 50, 60]
my_array.insert(2, 15) # [10, 25, 15, 30, 40, 50, 60]
# Removing elements
my_array.remove(25) # [10, 15, 30, 40, 50, 60]
popped = my_array.pop() # 60, array is now [10, 15, 30, 40, 50]
Intermediate Array Concepts
Array Slicing :
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# Basic slice
print(nums[2:5]) # [2, 3, 4]
# With step
print(nums[1:8:2]) # [1, 3, 5, 7]
# Negative indices
print(nums[-5:-2]) # [5, 6, 7]
# Omitting indices
print(nums[:3]) # [0, 1, 2]
print(nums[4:]) # [4, 5, 6, 7, 8, 9]
print(nums[::2]) # [0, 2, 4, 6, 8]
Array Methods :
# Sorting
numbers = [3, 1, 4, 1, 5, 9, 2]
numbers.sort() # [1, 1, 2, 3, 4, 5, 9]
numbers.sort(reverse=True) # [9, 5, 4, 3, 2, 1, 1]
# Reversing
numbers.reverse() # [1, 1, 2, 3, 4, 5, 9]
# Searching
index = numbers.index(4) # 3
count = numbers.count(1) # 2
# Copying
copy = numbers.copy() # Shallow copy
List Comprehensions :
# Basic comprehension
squares = [x**2 for x in range(10)]
# With condition
even_squares = [x**2 for x in range(10) if x % 2 == 0]
# Nested comprehension
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
Advanced Array Concepts
Multidimensional Arrays :
# 2D array (list of lists)
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# Accessing elements
print(matrix[1][2]) # 6
# Using NumPy for better performance
import numpy as np
np_matrix = np.array(matrix)
print(np_matrix[:, 1]) # Column at index 1: [2, 5, 8]
Array Performance Optimization :
# Time complexity of common operations
"""
Operation | Time Complexity
----------------+----------------
Index access | O(1)
Append | O(1)
Pop last | O(1)
Pop intermediate| O(n)
Insert | O(n)
Delete | O(n)
Search | O(n)
"""
# Using deque for faster appends/pops from both ends
from collections import deque
d = deque([1, 2, 3])
d.appendleft(0) # Faster than list.insert(0, 0)
d.popleft() # Faster than list.pop(0)
Memory Efficient Arrays :
# Using array module for homogeneous data
import array
int_arr = array.array('i', [1, 2, 3]) # More memory efficient than list
float_arr = array.array('d', [1.0, 2.0, 3.0])
# Typecodes:
# 'b' - signed char, 'B' - unsigned char
# 'i' - signed int, 'I' - unsigned int
# 'f' - float, 'd' - double
NumPy Arrays for Scientific Computing :
import numpy as np
# Creating NumPy arrays
arr = np.array([1, 2, 3]) # 1D array
matrix = np.array([[1, 2], [3, 4]]) # 2D array
# Array operations
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(a + b) # [5 7 9]
print(a * 2) # [2 4 6]
# Universal functions
print(np.sqrt(a)) # [1. 1.41421356 1.73205081]
Unique Array Techniques
Circular Buffer Implementation :
class CircularBuffer:
def __init__(self, size):
self.buffer = [None] * size
self.size = size
self.index = 0
def add(self, item):
self.buffer[self.index % self.size] = item
self.index += 1
def __getitem__(self, idx):
return self.buffer[idx % self.size]
def __repr__(self):
return str(self.buffer)
# Usage
cb = CircularBuffer(3)
cb.add(1); cb.add(2); cb.add(3); cb.add(4)
print(cb) # [4, 2, 3] - oldest element (1) was overwritten
Array-Based Queue :
class ArrayQueue:
def __init__(self):
self.items = []
def enqueue(self, item):
self.items.insert(0, item)
def dequeue(self):
return self.items.pop()
def size(self):
return len(self.items)
def is_empty(self):
return self.items == []
Memoryview for Efficient Array Manipulation :
# Using memoryview for efficient byte manipulation
data = bytearray(b'abcdef')
view = memoryview(data)
view[2:4] = b'XY'
print(data) # bytearray(b'abXYef')
Array-Based Binary Heap :
class MinHeap:
def __init__(self):
self.heap = []
def parent(self, i):
return (i-1)//2
def insert(self, key):
self.heap.append(key)
i = len(self.heap) - 1
while i != 0 and self.heap[self.parent(i)] > self.heap[i]:
self.heap[self.parent(i)], self.heap[i] = self.heap[i], self.heap[self.parent(i)]
i = self.parent(i)
def extract_min(self):
if not self.heap:
return None
if len(self.heap) == 1:
return self.heap.pop()
root = self.heap[0]
self.heap[0] = self.heap.pop()
self.heapify(0)
return root
def heapify(self, i):
smallest = i
left = 2*i + 1
right = 2*i + 2
if left < len(self.heap) and self.heap[left] < self.heap[smallest]:
smallest = left
if right < len(self.heap) and self.heap[right] < self.heap[smallest]:
smallest = right
if smallest != i:
self.heap[i], self.heap[smallest] = self.heap[smallest], self.heap[i]
self.heapify(smallest)
Performance Comparison :
import timeit
import numpy as np
from array import array
# List vs array module vs NumPy performance
size = 1_000_000
# Sum operation
list_time = timeit.timeit('sum(lst)', setup=f'lst = list(range({size}))', number=100)
array_time = timeit.timeit('sum(arr)', setup=f'arr = array.array("i", range({size}))', number=100)
numpy_time = timeit.timeit('np.sum(np_arr)', setup=f'import numpy as np; np_arr = np.arange({size})', number=100)
print(f"List sum: {list_time:.4f} sec")
print(f"Array sum: {array_time:.4f} sec")
print(f"NumPy sum: {numpy_time:.4f} sec")
Python Array (List) Methods Summary Table
| Method |
Description |
Example |
Output |
append(x) |
Adds item x to the end of the list |
fruits.append("orange") |
['apple', 'banana', 'cherry', 'orange'] |
insert(i, x) |
Inserts item x at position i |
fruits.insert(1, "grape") |
['apple', 'grape', 'banana', 'cherry'] |
remove(x) |
Removes first occurrence of x |
fruits.remove("banana") |
['apple', 'cherry'] |
pop([i]) |
Removes and returns item at index i (last if not given) |
fruits.pop() |
'cherry' |
sort() |
Sorts the list in ascending order |
numbers.sort() |
[1, 2, 3, 4, 5] |
reverse() |
Reverses the list |
numbers.reverse() |
[5, 4, 3, 2, 1] |
index(x) |
Returns index of first occurrence of x |
fruits.index("apple") |
0 |
count(x) |
Returns number of times x appears |
fruits.count("apple") |
1 |
copy() |
Returns a shallow copy of the list |
fruits.copy() |
['apple', 'banana', 'cherry'] |
extend(iterable) |
Adds all items from iterable to the end |
fruits.extend(["kiwi", "melon"]) |
['apple', 'banana', 'cherry', 'kiwi', 'melon'] |
clear() |
Removes all items from the list |
fruits.clear() |
[] |