Almost every AI, ML and GenAI interview has a Python round, and it is where many good candidates lose marks. They can explain transformers, but stumble when asked why a default argument changed between calls, or how to send a hundred LLM requests without waiting for each one.
This page has 28 Python interview questions for AI and ML roles with model answers, from core language basics to NumPy, pandas, scikit-learn, async LLM calls and short coding tasks. Code examples are kept short enough to write on a whiteboard or a shared editor.
I always tell freshers preparing for campus placements the same thing: interviewers do not need you to know every library. They need to trust that your Python is correct, readable and safe to put into a shared codebase.
Use the Save as PDF button above to keep an offline copy.
What do Python interviews for AI and ML roles test?
Python interviews for AI roles test whether you can write correct, efficient code for data and model work, not just solve puzzles.
| Area | Typical questions | Roles that stress it |
|---|---|---|
| Core Python | Lists vs tuples, dicts, generators, decorators, the GIL | Every AI and ML role |
| Data libraries | NumPy arrays, pandas cleaning, scikit-learn pipelines | ML engineer, data scientist |
| GenAI engineering | JSON parsing, API calls, async concurrency | AI engineer, GenAI developer |
| Engineering habits | Virtual environments, packaging, pytest | Product companies and startups |
| Live coding | Short tasks: word counts, chunking, similarity | Coding rounds and take-homes |
Freshers mostly face core Python and pandas questions. Experienced candidates get more on concurrency, performance, testing and code design.
How to prepare for a Python interview for AI roles
The fastest plan is to revise fundamentals, then practise with small programs that look like real AI work.
- Days 1 to 3: core Python. Data structures, comprehensions, functions, args and kwargs, classes, exceptions, generators and decorators. Write each from memory.
- Days 4 to 6: data libraries. NumPy indexing and broadcasting, pandas cleaning and grouping, and one end-to-end scikit-learn pipeline. Our machine learning interview questions page covers the theory side.
- Days 7 to 9: GenAI Python. Call an LLM API, validate JSON output with Pydantic, and run concurrent calls with asyncio. Revise embeddings and RAG.
- Days 10 to 12: engineering. Create a project with a virtual environment, a pinned requirements file and a few pytest tests.
- Days 13 to 14: timed practice. Solve the coding tasks at the end of this page in a plain editor, then explain each one out loud.
For the AI engineering rounds beyond Python, see our AI engineer interview questions for freshers.
Core Python interview questions for AI engineers
These come up in almost every first round. Answer directly, then show a tiny example.
1. What is the difference between a list and a tuple in Python?
EasyA list is mutable, so you can add, remove or change items, while a tuple is immutable once created. Use lists for collections that grow, such as chat messages in a conversation. Use tuples for fixed records, such as an (x, y) coordinate or a database row. Because tuples are immutable and hashable when their contents are hashable, they can be dictionary keys or set members; lists cannot. Tuples are also slightly lighter in memory.
2. How does a Python dictionary work, and why is lookup fast?
MediumA dictionary is a hash table: Python hashes each key to find where its value is stored, so lookups, inserts and deletes take constant time on average. That is why checking a key in a dict is much faster than searching a list for large data. Keys must be hashable, such as strings, numbers or tuples. Since Python 3.7, dicts officially preserve insertion order. In AI code, dicts map directly to JSON, so you use them constantly for API requests and responses.
3. What are list comprehensions, and when should you avoid them?
EasyA list comprehension builds a list in one readable expression, such as [w.lower() for w in words if w.isalpha()]. It is usually clearer and a little faster than an equivalent loop with append. Avoid it when the logic needs several conditions, nested loops or side effects like logging, because a regular loop is easier to read and debug. For very large data, use a generator expression with round brackets instead, so items are produced one at a time.
4. What is the difference between a generator and a list?
MediumA list stores every item in memory at once, while a generator produces items one at a time, only when asked. You create a generator with a function that uses yield, or with a generator expression. Generators suit large or endless data: reading a huge log file line by line, batching documents for embedding, or streaming tokens from an LLM response. The trade-off is that a generator can be consumed only once and does not support indexing or len().
5. What is a decorator in Python? Give an AI example.
MediumA decorator is a function that wraps another function to add behaviour without changing its code. A retry decorator for flaky API calls is a classic AI example:
import functools, time
def retry(times=3):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(times):
try:
return func(*args, **kwargs)
except Exception:
if attempt == times - 1:
raise
time.sleep(2 ** attempt)
return wrapper
return decoratorfunctools.wraps keeps the original function's name and docstring. In real code, retry only on transient errors such as timeouts.
6. What are args and kwargs in Python?
EasyThey let a function accept a variable number of arguments: args collects extra positional arguments into a tuple, and kwargs collects extra keyword arguments into a dictionary. In code, they are written with one and two asterisk prefixes respectively. They are common in wrappers and decorators, where you pass all arguments through to another function, such as forwarding model settings like temperature to an SDK call. Overusing them hides what a function expects, so prefer explicit parameters in public functions.
7. Why is a mutable default argument a bug in Python?
MediumDefault values are created once, when the function is defined, so a mutable default like a list is shared across every call:
def add_message(msg, history=[]): # bug: one list shared by all calls
history.append(msg)
return history
def add_message(msg, history=None): # fix
if history is None:
history = []
history.append(msg)
return historyIn a chatbot, the buggy version would leak one user's messages into another user's conversation, which is both a bug and a privacy problem.
Interviewer tip: Mention the privacy angle. It shows you think about real users, not just output.
8. What is the GIL, and how does it affect AI workloads?
HardThe Global Interpreter Lock (GIL) in CPython lets only one thread execute Python bytecode at a time, so threads do not speed up CPU-heavy pure Python code. It matters less than people expect in AI work: threads still help with I/O such as API calls, because the lock is released while waiting, and libraries like NumPy and PyTorch run heavy maths in C or on GPUs, often outside the lock. For CPU-bound Python, use multiprocessing. Python 3.13 added an optional free-threaded build without the GIL; check its status for your version.
9. What is the difference between a shallow copy and a deep copy?
EasyA shallow copy creates a new outer object but shares the nested objects inside it, while a deep copy recursively copies everything. If you shallow-copy a list of message dicts and then edit one dict, the original changes too. Use copy.deepcopy when you need fully independent nested data, such as cloning a configuration before changing it for an experiment. Deep copies are slower and use more memory, so do not use them by default.
Python AI ML interview questions: NumPy, pandas and scikit-learn
Data roles lean heavily on this section. Pair it with our data scientist interview questions.
1. Why is NumPy faster than Python lists for numerical work?
MediumNumPy stores numbers of one type in a contiguous block of memory and runs operations in optimised compiled code, while a Python list stores references to separate Python objects. That lets NumPy apply one operation to a whole array at once, called vectorisation, instead of looping in Python. Adding two arrays of a million floats with a + b is far faster than a list loop. The trade-off: arrays have a fixed type and size, so appending item by item is slow.
2. What is broadcasting in NumPy?
MediumBroadcasting lets NumPy perform operations on arrays of different shapes by virtually stretching the smaller one, without copying data. Shapes are compared from the last dimension backwards; each pair must be equal or one of them must be 1. For example, subtracting a mean vector of shape (5,) from a matrix of shape (1000, 5) centres every row in one line. Broadcasting is efficient but can hide shape bugs, so check array shapes when results look wrong.
3. How do you handle missing values in pandas?
EasyFirst measure them with df.isna().sum(), then choose a strategy per column based on why the data is missing. Options include dropping rows with dropna, filling with a constant, the median or the most frequent value using fillna, or adding an indicator column that marks missingness. For time series, forward fill is common. Never fill blindly: a missing income value in a loan dataset may itself be a signal. Compute fill values on training data only to avoid leakage.
4. What is the difference between loc and iloc in pandas?
Easyloc selects rows and columns by label, while iloc selects by integer position. For example, df.loc[df["city"] == "Pune", "salary"] filters by a condition and a column name, while df.iloc[0:5, 2] takes the first five rows of the third column. A common trap: loc slices include the end label, while iloc slices exclude the end position, like normal Python slicing. Use loc for readable, label-based code and iloc when position genuinely matters.
5. Explain the scikit-learn workflow with fit, transform and predict.
MediumScikit-learn uses a consistent interface: you create an estimator, call fit on training data to learn parameters, then call predict on new data, or transform for preprocessing steps like scaling. For example, StandardScaler learns each column's mean and standard deviation in fit, then applies them in transform. A model like LogisticRegression learns weights in fit and outputs classes in predict. This shared interface lets you swap models easily and chain steps in a Pipeline.
6. What is data leakage, and how do scikit-learn pipelines prevent it?
HardData leakage is when information from the test set, or from the future, sneaks into training, so validation scores look better than real-world performance. A classic example is scaling or imputing using statistics from the whole dataset before splitting. A Pipeline bundles preprocessing and the model, so during cross-validation each fold fits the preprocessing on its own training part only. Leakage also comes from features that would not exist at prediction time, so check each feature's timing.
7. Why is df.apply slow, and what should you use instead?
Mediumapply with a custom Python function runs that function row by row in Python, so it loses the speed of pandas' vectorised operations. Prefer built-in vectorised methods: arithmetic on whole columns, the .str methods for text, np.where for conditions, and map for simple lookups. For example, multiplying the price and qty columns directly is much faster than an apply with a lambda that multiplies them row by row. apply is still fine for small data or genuinely complex logic where readability matters more.
Python interview questions for gen AI: JSON, LLM APIs and async
GenAI engineer interviews add these to the core round. For the model theory, see our generative AI interview questions.
1. How do you parse and validate JSON returned by an LLM?
MediumParse with json.loads inside a try block, then validate the structure with a schema library such as Pydantic. LLM output can include extra text, missing fields or wrong types, so parsing alone is not enough. Define a Pydantic model with the expected fields and types, call model_validate on the parsed dict, and catch validation errors. On failure, retry once with the error message added to the prompt, or fall back safely. Provider JSON or structured output modes reduce, but do not remove, the need for validation.
2. What is async and await in Python?
Mediumasync and await let one thread handle many waiting tasks at the same time through an event loop. An async function returns a coroutine; await pauses it while it waits for I/O, such as a network response, and the event loop runs other tasks meanwhile. It suits I/O-bound work like calling LLM APIs, databases or web pages. It does not speed up CPU-heavy work, and one blocking call inside an async function stalls everything on that loop.
3. How would you call an LLM API for 100 inputs concurrently?
HardUse an async client with asyncio.gather, and limit concurrency with a semaphore so you stay within rate limits:
import asyncio
from openai import AsyncOpenAI
client = AsyncOpenAI()
sem = asyncio.Semaphore(10) # at most 10 requests in flight
async def classify(text):
async with sem:
resp = await client.chat.completions.create(
model="your-model-name",
messages=[{"role": "user", "content": text}],
)
return resp.choices[0].message.content
async def run_all(texts):
return await asyncio.gather(*(classify(t) for t in texts), return_exceptions=True)return_exceptions keeps one failure from cancelling the rest. Add retries with backoff for 429 errors.
4. Threading vs multiprocessing vs asyncio: when do you use each?
HardUse asyncio for many concurrent I/O tasks with async-ready libraries, threading for I/O work with blocking libraries, and multiprocessing for CPU-heavy pure Python work. Sending 500 LLM requests fits asyncio. Downloading files with a blocking library fits a thread pool. Cleaning millions of text records with Python logic fits a process pool, because each process has its own interpreter and GIL. Processes cost more memory and data must be serialised between them, so do not reach for them by default.
5. How do you process a dataset that does not fit in memory?
MediumProcess it in pieces instead of loading it all at once. With pandas, read_csv accepts a chunksize argument and returns an iterator of smaller DataFrames you can process and aggregate. For text files, iterate line by line, or write a generator that yields batches, which also works well for sending documents to an embedding API in groups. Columnar formats like Parquet let you load only the columns you need. Larger workloads may justify tools such as Polars, DuckDB or Spark.
6. What are type hints, and why do AI codebases use them?
EasyType hints annotate the expected types of variables, parameters and return values, such as def embed(texts: list[str]). Python does not enforce them at runtime by default, but tools like mypy and editors use them to catch bugs early. In AI codebases they matter more because libraries such as Pydantic and FastAPI read type hints to validate data and generate API schemas. They also make code easier for teammates, and AI coding assistants, to understand.
Python coding interview questions for AI engineer roles: environments, testing and tasks
Expect at least one of these in a live coding round. Talk through edge cases as you write.
1. What is a virtual environment, and why do you need one?
EasyA virtual environment is an isolated Python setup with its own installed packages, so each project can use its own library versions. Without one, upgrading a library for one project can break another. You create one with python -m venv .venv, activate it, and install dependencies inside it. Tools like uv, Poetry or conda add faster installs and lock files. Always keep the environment folder out of git and share the dependency file instead.
2. How do you manage dependencies and package a Python project?
MediumList dependencies in a requirements.txt or, in modern projects, a pyproject.toml, and pin versions so builds are reproducible. Lock files, generated by tools such as pip-tools, Poetry or uv, record exact versions including sub-dependencies. AI projects need this discipline because libraries like torch, transformers and LLM SDKs change often and break older code. To share code as a package, define it in pyproject.toml and build a wheel. Keep development-only tools, like pytest, separate from runtime dependencies.
3. How do you write tests for Python AI code with pytest?
MediumWrite small test functions that start with test_ and use plain assert statements; pytest finds and runs them automatically:
# test_chunker.py
from chunker import chunk_words
def test_chunks_overlap():
chunks = chunk_words("a b c d e f", size=4, overlap=2)
assert chunks == ["a b c d", "c d e f"]
def test_empty_text():
assert chunk_words("", size=4, overlap=2) == []Test deterministic parts, such as chunking, parsing and validation, directly. Mock LLM calls in unit tests so they stay fast and free, and keep a separate evaluation set for output quality.
4. Coding task: return the 5 most common words in a text.
EasyNormalise the text, extract words with a regular expression and count them with collections.Counter:
import re
from collections import Counter
def top_words(text, k=5):
words = re.findall(r"[a-z']+", text.lower())
return Counter(words).most_common(k)Counter.most_common returns (word, count) pairs sorted by frequency. Mention follow-ups the interviewer may ask: removing stopwords like "the" and "is", handling Hindi or other Unicode scripts (this simple pattern only matches English letters), and processing a very large file line by line.
5. Coding task: split a long text into overlapping chunks for RAG.
MediumSplit into words, then step through with a stride of size minus overlap:
def chunk_words(text, size=200, overlap=40):
if overlap >= size:
raise ValueError("overlap must be smaller than size")
words = text.split()
step = size - overlap
chunks = []
for start in range(0, len(words), step):
chunks.append(" ".join(words[start:start + size]))
if start + size >= len(words):
break
return chunksOverlap keeps sentences that cross a boundary retrievable from either chunk. Real systems usually count tokens rather than words and split on headings or paragraphs first.
6. Coding task: implement cosine similarity with NumPy.
MediumCosine similarity is the dot product of two vectors divided by the product of their lengths:
import numpy as np
def cosine_similarity(a, b):
a = np.asarray(a, dtype=float)
b = np.asarray(b, dtype=float)
denom = np.linalg.norm(a) * np.linalg.norm(b)
return float(a @ b / denom) if denom else 0.0To compare one query against many document embeddings, normalise all rows once and compute a single matrix product, which is far faster than a Python loop. Guard against zero vectors, as above.
Interviewer tip: Expect the follow-up: how would you find the top 3 matches? Use np.argsort or np.argpartition.
Common mistakes in Python interviews for AI roles
The most common mistake is writing code that works on the happy path and nowhere else.
- Ignoring edge cases. Empty input, a missing JSON key or a zero vector should not crash your function. Mention them before the interviewer does.
- Notebook habits in interviews. Global variables everywhere and cells run out of order make code hard to trust. Write small functions.
- Looping over DataFrames. Iterating row by row in pandas when a vectorised operation exists signals inexperience.
- Overclaiming async knowledge. Do not say async makes code faster in general. It helps with waiting, not computing.
- Silent exception handling. A bare except that hides every error makes debugging AI pipelines painful.
My contrarian tip: skip memorising obscure language trivia. Interviewers for AI roles care far more about clean functions, sensible data handling and tests than about tricky questions on metaclasses.
Last-week Python revision plan before an AI interview
In the final week, write code by hand every day instead of only reading.
- Day 1: Data structures, comprehensions, generators and decorators from memory.
- Day 2: Mutable defaults, copies, args and kwargs, exceptions and the GIL.
- Day 3: NumPy broadcasting and pandas cleaning on a real CSV.
- Day 4: One scikit-learn Pipeline with cross-validation.
- Day 5: JSON validation and concurrent LLM calls with asyncio.
- Day 6: The coding tasks on this page, timed, then explained aloud.
- Day 7: Light revision, rest and a quick check of your coding setup for online rounds.
Revise what an LLM is too, because Python rounds for GenAI roles often drift into model questions.
Your interview prep checklist
- Explain lists, tuples, dicts, generators and decorators with a code example each.
- Explain the GIL and when to use asyncio, threads or processes.
- Clean a messy CSV in pandas without looping row by row.
- Build one scikit-learn Pipeline and explain how it prevents leakage.
- Write concurrent LLM calls with asyncio and a semaphore from memory.
- Solve the word count, chunking and cosine similarity tasks in a plain editor.