A list is one of Python's most powerful, versatile, and ubiquitous built-in data structures. Under the hood in CPython, a list is implemented as a dynamic contiguous array of object pointers. This provides O(1) amortized append operations and ultra-fast O(1) random index access. In this comprehensive class, you will master list operations, methods, sorting algorithms, and memory copying mechanisms.
Lists are constructed using square brackets [] or via the list() constructor:
# Empty list:
empty_list = []
# List with mixed (heterogeneous) data types:
student_record = [101, "Neha Gupta", 92.5, True, ["BCA", "Semester 3"]]
print("Total elements:", len(student_record))
print("Nested element:", student_record[4][0]) # 'BCA'
append(), insert(), extend()Understanding how elements are added is critical for university exams and interviews:
fruits = ["Apple", "Banana"]
# 1. append(item): Adds single element at the end (O(1))
fruits.append("Orange")
print("After append:", fruits) # ['Apple', 'Banana', 'Orange']
# 2. insert(index, item): Inserts at specific position (O(n))
fruits.insert(1, "Mango")
print("After insert at 1:", fruits) # ['Apple', 'Mango', 'Banana', 'Orange']
# 3. extend(iterable): Unpacks and appends multiple items (O(k))
tropical = ["Papaya", "Guava"]
fruits.extend(tropical)
print("After extend:", fruits) # ['Apple', 'Mango', 'Banana', 'Orange', 'Papaya', 'Guava']
remove(), pop(), clear(), delnumbers = [10, 20, 30, 40, 50, 20]
# remove(val): Removes FIRST matching value
numbers.remove(20) # Removes first 20
print("After remove(20):", numbers) # [10, 30, 40, 50, 20]
# pop(index): Removes and returns element at index (defaults to last)
last_item = numbers.pop()
print(f"Popped: {last_item}, Remaining: {numbers}") # Popped 20
# del statement: Removes by index or slice
del numbers[0] # Removes 10
# clear(): Removes all elements, leaving an empty list []
numbers.clear()
print("After clear:", numbers) # []
sort() vs sorted()Python uses Timsort (an adaptive merge-insertion hybrid sort with O(n log n) worst-case time complexity):
• list.sort(): Sorts the list in-place, returning None. Modifies original list.
• sorted(list): Returns a brand-new sorted copy, leaving original list untouched.
scores = [88, 42, 95, 71, 63]
# In-place descending sort:
scores.sort(reverse=True)
print("Sorted in-place (descending):", scores) # [95, 88, 71, 63, 42]
# Custom sort by key (e.g. length of strings):
words = ["python", "c", "javascript", "go"]
words.sort(key=len)
print("Sorted by length:", words) # ['c', 'go', 'python', 'javascript']
import copy
# Problem with simple assignment (=):
original = [1, [2, 3]]
alias = original # BOTH point to same memory address!
# Shallow Copy:
shallow = copy.copy(original)
# Deep Copy:
deep = copy.deepcopy(original)
original[1][0] = 999 # Modify nested sub-list!
print("Shallow copy affected?:", shallow[1][0]) # 999 (YES! Shared nested reference)
print("Deep copy affected?: ", deep[1][0]) # 2 (NO! Completely isolated clone)
Challenge: Given a list of numbers, remove all duplicate elements while preserving the original order of first appearance:
def remove_duplicates(lst):
seen = set()
result = []
for item in lst:
if item not in seen:
seen.add(item)
result.append(item)
return result
sample_list = [1, 5, 2, 1, 9, 2, 4, 5, 10]
print("Unique list:", remove_duplicates(sample_list))
# Output: [1, 5, 2, 9, 4, 10]
tuple instead.