Using Python Well in Interviews
35 min · Beginner
Need help? Ask a tutor on WhatsApp (opens in a new tab)Python can solve a small job in one line. In an interview, the skill is knowing when to use that line and when to show the work behind it.
Python's tools are fine when the idea is yours
Idiomatic Python is code that uses the language's own tools, such as enumerate, sorted, Counter and comprehensions, the way Python programmers normally write it. It reads shorter and is usually less error-prone.
Python ships many tools that solve small jobs in one line. Using them well shows you know the language. Using them to dodge the question does not.
from collections import Counter
words = "to be or not to be".split()print(Counter(words).most_common(2))Example 1 · Counting: Counter, then by hand
from collections import Counter
text = "banana"print(Counter(text))
counts = {}for ch in text: counts[ch] = counts.get(ch, 0) + 1print(counts)Counter({'a': 3, 'n': 2, 'b': 1})
{'b': 1, 'a': 3, 'n': 2}What this code does
- Both build the same counts.
Counteris one line; the dictionary version shows the idea of looking up with a default of 0. - Use
Counterwhen counting is a step. If asked "without any imports", show the dictionary loop.
Counter counts how many times each item appears. most_common(2) returns the two most frequent items as (item, count) pairs. If counting is only a step in your answer, using it is fine.
When sorted is fine
A built-in sort, sorted() or list.sort(), orders items in O(n log n) time. sorted returns a new list and sort changes the list in place. Both accept a key function to choose what to compare.
Sorting is a step in many answers, not the answer itself. Say what sorted costs, and use it when the sort is not the thing being tested.
marks = [78, 91, 85, 66, 91]top_three = sorted(marks, reverse=True)[:3]print(top_three)Example 2 · The top three with sorted, and a key
orders = [("T-101", 450), ("T-102", 1200), ("T-103", 300), ("T-104", 980)]largest = sorted(orders, key=lambda order: order[1], reverse=True)[:3]print(largest)print(sorted(["pune", "Delhi", "chennai"], key=str.lower))[('T-102', 1200), ('T-104', 980), ('T-101', 450)]
['chennai', 'Delhi', 'pune']What this code does
key=says what to compare: here the amount in each pair, then the lower-case name.- The cost is O(n log n) for the sort. For only the single largest,
max(orders, key=...)does one pass.
Example 3 · Selection sort by hand
def selection_sort(values): items = list(values) for i in range(len(items)): smallest = i for j in range(i + 1, len(items)): if items[j] < items[smallest]: smallest = j items[i], items[smallest] = items[smallest], items[i] return items
marks = [64, 25, 12, 22, 11]print(selection_sort(marks))print(selection_sort(marks) == sorted(marks))[11, 12, 22, 25, 64] True
What this code does
- Here the index loops are the point: find the smallest remaining item and swap it into place. It takes O(n squared) time.
- Checking the answer against
sortedis a good habit in practice, since it gives a trusted result to compare with.
sorted returns a new list and leaves marks unchanged. It takes O(n log n) time. If the question is "find the largest", one pass is O(n), so say that the sort is more work than needed.
When an interviewer wants it by hand
Writing it by hand means building the logic yourself with loops and basic types instead of calling a library helper that already solves the whole question. It is usually asked when the helper is exactly what is being tested.
Sometimes the library call is the whole question. Reversing a string with [::-1] or comparing two Counter objects can skip what the interviewer wanted to see. Ask which they prefer.
def reverse_by_hand(text): chars = list(text) left, right = 0, len(chars) - 1 while left < right: chars[left], chars[right] = chars[right], chars[left] left += 1 right -= 1 return "".join(chars)Example 4 · Reverse a string three ways
def reverse_by_hand(text): chars = list(text) left, right = 0, len(chars) - 1 while left < right: chars[left], chars[right] = chars[right], chars[left] left += 1 right -= 1 return "".join(chars)
word = "python"print(reverse_by_hand(word), word[::-1], "".join(reversed(word)))nohtyp nohtyp nohtyp
What this code does
- All three give the same result. The slice and
reversedare right for real code; the pointer version is what a "do it manually" question wants. - Strings cannot be changed in place, so the manual version first copies the characters into a list.
Example 5 · Anagram check: Counter, then by hand
from collections import Counter
def is_anagram_counter(a, b): return Counter(a) == Counter(b)
def is_anagram_by_hand(a, b): if len(a) != len(b): return False counts = {} for ch in a: counts[ch] = counts.get(ch, 0) + 1 for ch in b: if counts.get(ch, 0) == 0: return False counts[ch] -= 1 return True
for pair in [("listen", "silent"), ("abc", "abd")]: print(is_anagram_counter(*pair), is_anagram_by_hand(*pair))True True False False
What this code does
- Both are O(n) time. If you use
Counter, say so, then offer the manual version if the interviewer wants to see the counting. *pairunpacks the two words into the two arguments.
Two pointers walk in from both ends and swap. A good line to say first: "I can do this with [::-1]; do you want me to show the manual version?" Asking costs nothing and shows judgement.
Know the hidden cost of a short line
A hidden cost is work that a short line does behind the scenes, such as in on a list scanning every item or list.pop(0) shifting the whole list. One short line can still be slow, so know the cost of each call you use.
A short line can hide a loop. Checking x in some_list scans the list, and list.pop(0) shifts every item. Know which short lines are expensive.
from collections import deque
queue = deque(["T-101", "T-102"])queue.append("T-103")print(queue.popleft())Example 6 · A queue without the hidden cost
from collections import deque
tickets = ["T-101", "T-102", "T-103"]print(tickets.pop(0))
queue = deque(["T-101", "T-102", "T-103"])print(queue.popleft())print(queue)T-101 T-101 deque(['T-102', 'T-103'])
What this code does
- Both remove the first ticket. On a list,
pop(0)shifts every other item, so it costs O(n);deque.popleft()costs O(1). - On three items it makes no difference, but on a million it does. Interviewers like to hear that you know why.
deque.popleft() removes from the front in constant time. The same job with list.pop(0) moves every remaining item, so it takes time in step with the list length.
Next step
Check your understanding
10 quick questions