Skip to content

Python · Data Structures

Python Lists and Slicing Explained — append vs extend, sort vs sorted, and Negative Steps

4 min read Updated 2026-06-19 Share:

Practice Lists & Slicing interview questions

Python lists, explained

The list is Python's workhorse sequence, and interviewers use it to check whether you understand slicing, in-place vs returning operations, and the cost of the operations you reach for. This guide covers slicing mechanics, the append/extend/insert distinction, and sort vs sorted.

Lists vs arrays

A Python list is a dynamic, heterogeneous sequence of object references — it can hold mixed types and resize automatically:

mixed = [1, "two", 3.0, [4]]   # perfectly legal

It is not a contiguous block of numbers like a C array. For large numeric data, use array.array (typed) or, in practice, NumPy arrays, which store raw values compactly and run far faster for math.

Slicing, including negative steps

Slicing uses [start:stop:step], where stop is exclusive and any part can be omitted:

nums = [0, 1, 2, 3, 4, 5]
nums[1:4]      # [1, 2, 3]
nums[:3]       # [0, 1, 2]
nums[2:]       # [2, 3, 4, 5]
nums[::2]      # [0, 2, 4]      — every other element
nums[-2:]      # [4, 5]         — last two
nums[::-1]     # [5, 4, 3, 2, 1, 0]  — reversed

A slice creates a shallow copynums[:] is a common way to copy a list. The copy is shallow, so nested objects are shared, not duplicated.

Slice assignment

You can assign to a slice to replace, insert, or delete a whole region in place:

nums = [0, 1, 2, 3, 4]
nums[1:3] = ["a", "b", "c"]    # [0, 'a', 'b', 'c', 3, 4] — replace with different length
nums[:] = []                   # clears the list in place

append vs extend vs insert

These three add elements but differ in what and where:

lst = [1, 2]
lst.append([3, 4])   # [1, 2, [3, 4]]  — adds ONE element (the list itself)

lst = [1, 2]
lst.extend([3, 4])   # [1, 2, 3, 4]    — adds each element of the iterable

lst = [1, 2]
lst.insert(0, 99)    # [99, 1, 2]      — insert at an index (O(n): shifts elements)

append is O(1) amortised; insert(0, x) is O(n) because everything shifts. If you frequently add to the front, use collections.deque instead.

sort vs sorted

list.sort() sorts in place and returns None; sorted() returns a new sorted list and works on any iterable:

nums = [3, 1, 2]
nums.sort()              # nums is now [1, 2, 3]; returns None
result = nums.sort()     # BUG: result is None

squared = sorted([3, 1, 2])   # [1, 2, 3], original untouched

Both accept key and reverse, and both are stable (equal elements keep their order):

words = ["bb", "a", "ccc"]
sorted(words, key=len)            # ['a', 'bb', 'ccc']
sorted(words, key=len, reverse=True)

Are comprehensions faster than loops?

Yes, modestly — a list comprehension is usually faster than the equivalent for loop with .append(), because the iteration and appending happen in C rather than via repeated attribute lookups and method calls:

squares = [x * x for x in range(1000)]   # faster + clearer than a loop

Use a comprehension when you're building a list; use a plain loop when you're doing it for side effects.

Recap

A list is a resizable, heterogeneous sequence of references — reach for NumPy when you need fast numeric arrays. Slicing [start:stop:step] is exclusive of stop, supports negative steps ([::-1] reverses), and returns a shallow copy. append adds a single item, extend adds each item of an iterable, and insert is O(n). Use list.sort() for an in-place sort (returns None) and sorted() to get a new list; both are stable and take a key. Prefer comprehensions when building lists.

More ways to practice

The self-quiz is live. Get notified when mock interviews and new question packs drop.

or
Join our WhatsApp Channel