◐ ai-teacher

🎯 Interview & Career · Chapter 3

The Python round: what they're really testing

A data engineering Python round is rarely about clever algorithms. It's a messy file, a dictionary and a question: will your code survive the 10 millionth line, the malformed one, and the next engineer who reads it?

Study this lesson free in the app →

The basics

The Python round for data engineers usually gives you records — log lines, JSON events, a CSV — and asks you to clean, deduplicate, aggregate or join them, live, in a shared editor. Sometimes pandas or PySpark is allowed; often it's plain Python on purpose.

What they're really testing:

The mental model: treat it as a mini pipeline — parse → validate → transform → aggregate → output — with each step a function you can test.

Words to know: O(n) / O(n log k), generator, defaultdict, heapq, idempotent, malformed record.

Explained

Interviewer: “Here's a file of ride events, one JSON per line. Return each driver's total completed fare. Events can be duplicated.”

The 5-line sample works with any approach. Then the follow-ups: “The file is 40 GB. … Line 3 million is truncated. … Now give me the top 5 drivers.”

Each follow-up tests one thing: streaming, robustness, data-structure choice. The first answer was just the warm-up.

Sorting the post office

A post office in Shillong gets 50,000 letters a day.

The new clerk tries to hold them all in his arms, then sort. (reading the whole file into memory) Then he checks each letter against a handwritten list of already-delivered ones, top to bottom. (in list, O(n) per letter) A torn envelope with no address stops him for an hour. (one malformed line crashes everything)

The experienced clerk takes letters one at a time from the bag, drops each into a labelled pigeonhole (dict), checks a stamped register for duplicates (set), and puts torn ones in a ‘problem’ tray to count later.

Same job. One clerk scales, one doesn't. That's the difference they're interviewing for.

Every DE Python answer has this shape

Say this shape out loud before coding: “I'll read, parse, validate, dedupe, aggregate, output — each as its own small function.” It shows decomposition in one sentence and gives you a map for the rest of the round.

A solution that survives the follow-ups

import json, heapq, logging
from collections import defaultdict

def read_events(path):
    """Stream events; skip and count malformed lines."""
    bad = 0
    with open(path) as f:
        for line in f:                       # one line in memory at a time
            try:
                yield json.loads(line)
            except json.JSONDecodeError:
                bad += 1
    logging.info("skipped %d malformed lines", bad)

def driver_totals(events):
    seen, totals = set(), defaultdict(float)
    for e in events:
        eid = e.get("event_id")
        if eid is None or eid in seen:       # O(1) membership
            continue
        seen.add(eid)
        if e.get("type") == "completed" and e.get("fare") is not None:
            totals[e["driver"]] += float(e["fare"])
    return totals

def top_drivers(totals, k=5):
    return heapq.nlargest(k, totals.items(), key=lambda kv: kv[1])  # O(n log k)

totals = driver_totals(read_events("rides.jsonl"))
print(top_drivers(totals))

Three functions, each one sentence to explain. Say out loud: “the seen set grows with distinct events — at billions I'd dedupe per day or use the warehouse.”

The scoring sheet, translated

For data roles, add scale judgement: knowing when to say “at this size I wouldn't do it in Python — I'd load it and GROUP BY in the warehouse or use PySpark.” That sentence is often worth more than a micro-optimisation.

How candidates lose the Python round

The follow-up ladder

Interviewers rarely stop at the first solution. Expect this ladder and have a sentence ready for each rung:

  1. “It's 40 GB.” → stream lines with a generator; memory now depends on distinct drivers, not file size.
  2. “Some lines are broken.” → try/except JSONDecodeError, count, log, continue; fail the job if bad > 1%.
  3. “Top 5 drivers.” → heapq.nlargest — O(n log k).
  4. “Duplicates across days.” → the seen-set grows forever; dedupe per day partition, or push dedupe to the warehouse with a unique key.
  5. “How would you test it?” → three tests: empty file, one malformed line, a duplicated completed event.
  6. “Make it run daily in production.” → idempotent output per date, overwrite the partition, schedule in Airflow, alert on bad-line rate.

Stream it, structure it, survive bad lines, state the complexity, test the edges.

dict for lookup, set for dedupe, heap for top-k — and know when to say ‘this belongs in the warehouse’.

Words to know

GeneratorA function using yield that produces items one at a time, keeping memory constant for large inputs.
Time complexityHow runtime grows with input size, e.g. O(n) single pass, O(n²) nested scan.
heapq.nlargestReturns the k largest items in O(n log k) without sorting everything.
defaultdictA dict that creates a default value (0, [], …) for missing keys — tidy grouping.
Malformed recordAn input line that can't be parsed or fails validation; handle by skip-count-log or fail.
Set membershipx in set is O(1) on average; x in list is O(n).

In two minutes

Test yourself

1. Which structure is best for checking whether an event_id has already been seen?

  1. list
  2. set
  3. tuple
  4. string
Show the answer

set — Set membership is O(1) on average. A list scan is O(n) per check, O(n²) overall.

2. The input file is 40 GB and your laptop has 16 GB RAM. How should you read it?

  1. f.read() then split
  2. f.readlines()
  3. Iterate `for line in f` (or a generator) one line at a time
  4. Load into a pandas DataFrame in one go
Show the answer

Iterate `for line in f` (or a generator) one line at a time — Iterating a file object streams lines, so memory depends on what you keep (totals), not file size.

3. Complexity of heapq.nlargest(5, items) over n items?

  1. O(n log k), with k = 5
  2. O(n log n)
  3. O(1)
  4. O(n²)
Show the answer

O(n log k), with k = 5 — It maintains a heap of size k while scanning: O(n log k), effectively linear for small k. Sorting everything is O(n log n).

4. Line 3,000,000 is truncated JSON. Best behaviour for a daily job?

  1. Crash the whole job
  2. Silently skip it
  3. Retry the line forever
  4. Catch JSONDecodeError, count and log it, continue; fail if the bad rate exceeds a threshold
Show the answer

Catch JSONDecodeError, count and log it, continue; fail if the bad rate exceeds a threshold — One bad line shouldn't stop 3 million good ones, but silent skipping hides upstream breakage. Count, log, and set a failure threshold.

5. What is the main memory risk in dedupe-with-a-set at very large scale?

  1. Sets are slow
  2. The set holds every distinct id ever seen and grows without bound
  3. Sets can't hold strings
  4. Sets lose items
Show the answer

The set holds every distinct id ever seen and grows without bound — Mention it unprompted: partition dedupe by day, use the warehouse with a unique key, or a probabilistic structure if approximate is acceptable.

6. Trap: the interviewer says pandas is not allowed. Why might they do that?

  1. The company bans pandas
  2. Pandas is too slow for 5 lines
  3. To see whether you understand the underlying data structures and complexity
  4. To make it harder for no reason
Show the answer

To see whether you understand the underlying data structures and complexity — groupby hides the dict-of-accumulators idea. Without it, they can see whether you know what the library does for you.

There are 8 questions, 3 puzzles and 5 recall cards for this lesson in the app — the recall cards come back on later days, just before you would forget.

Learn it so it stays. Read it, test yourself, then recall it on two different days. The app schedules that for you, free.

Start this lesson →