Lists & Slicing Interview Questions & Answers
5 questions Updated 2026-06-18
Python interview questions on lists vs arrays, slicing semantics and negative steps, append vs extend vs insert, comprehensions, and sort vs sorted.
A list is Python's built-in, dynamically-sized, heterogeneous
container — it can hold objects of any type because each slot stores a
reference to a boxed Python object. The standard-library array.array
(and NumPy's ndarray) is homogeneous and typed, storing raw C values
contiguously, which is far more memory-efficient for large numeric data.
from array import array
nums = [1, 2, "three"] # list — mixed types allowed
typed = array("i", [1, 2, 3]) # array — all C ints, compact
typed.append("x") # TypeError — type-checked
import sys
sys.getsizeof([1, 2, 3]) # bigger: stores pointers
sys.getsizeof(array("i", [1, 2, 3])) # smaller: packed ints
Rule of thumb: reach for a plain list for general-purpose, mixed-type
collections; use array or NumPy when you have large amounts of
uniform numeric data and care about memory or vectorized speed.
A slice is lst[start:stop:step]. start is inclusive, stop is
exclusive, and any part can be omitted (defaults: start of list, end of
list, step 1). A negative step walks the list backwards, and when it's
negative the defaults for start/stop flip to the end and the
beginning.
a = [0, 1, 2, 3, 4, 5]
a[1:4] # [1, 2, 3] — stop is exclusive
a[:3] # [0, 1, 2] — omitted start = 0
a[::2] # [0, 2, 4] — every other element
a[::-1] # [5, 4, 3, 2, 1, 0] — reversed copy
a[4:1:-1] # [4, 3, 2] — backwards, stop exclusive
Slicing never raises for out-of-range indices (a[10:20] is just []),
unlike single-element indexing. Remember a[::-1] is the idiomatic way to get a
reversed shallow copy.
append(x) adds a single item to the end in amortized O(1).
extend(iterable) adds each element of an iterable to the end (also
amortized O(1) per element). insert(i, x) places an item at index i,
which is O(n) because every following element must shift right.
a = [1, 2, 3]
a.append([4, 5]) # [1, 2, 3, [4, 5]] — the LIST is one element
a = [1, 2, 3]
a.extend([4, 5]) # [1, 2, 3, 4, 5] — unpacks the iterable
a.insert(0, 99) # [99, 1, 2, 3, 4, 5] — O(n) shift
The classic trap: append([4, 5]) nests the whole list as one item, whereas
extend([4, 5]) merges its elements. Avoid insert(0, …) in a loop — it's
O(n) each time; use collections.deque for fast front insertion.
Usually yes. A comprehension runs its iteration in optimized C-level
bytecode and avoids the repeated list.append attribute lookup and method
call that a manual loop incurs, so it's typically 20–40% faster as well as
more concise. It also creates the loop variable in its own scope, so it
doesn't leak.
# manual loop — explicit append each iteration
squares = []
for n in range(1000):
squares.append(n * n)
# comprehension — faster and clearer
squares = [n * n for n in range(1000)]
Use a comprehension when you're building a list from an expression. But if
the body has side effects or grows complex (nested conditionals, multiple
statements), a readable for loop is the better choice — clarity beats a small
speed win.
list.sort() sorts a list in place and returns None — it mutates
the original and only works on lists. sorted(iterable) returns a new
sorted list and leaves the input untouched, accepting any iterable (tuples,
sets, generators, dict keys).
nums = [3, 1, 2]
result = nums.sort() # result is None! nums is now [1, 2, 3]
original = (3, 1, 2)
new = sorted(original) # new = [1, 2, 3], original unchanged
sorted(["bb", "a"], key=len, reverse=True) # ['bb', 'a']
Both are stable (equal elements keep their order) and run in O(n log n)
(Timsort). Watch the gotcha: x = mylist.sort() leaves x as None. Use
sort() to save memory when you don't need the original; use sorted() when you
must preserve it or are sorting a non-list iterable.
Practice tests are coming soon
Get notified when interactive mock interviews and quizzes launch.