Skip to content

🎯 07 – Interview Questions: Python Basics

These are real questions asked in Data Science and Python developer interviews.


🔢 Variables & Data Types

Q1: What is the difference between is and == in Python?

Show answer

== compares values; is compares identity (same object in memory).

a = [1, 2, 3]
b = [1, 2, 3]
print(a == b)   # True  (same values)
print(a is b)   # False (different objects)

c = a           # c points to the same object
print(a is c)   # True

Rule: Use is only for None, True, False comparisons. Use == for value comparisons.


Q2: What is the output of 0.1 + 0.2 == 0.3? Why?

Show answer

False. Floating point numbers can't be represented exactly in binary. Use abs(0.1 + 0.2 - 0.3) < 1e-9 to compare floats.


Q3: What is the difference between int and float? When does division return a float?

Show answer

int stores whole numbers; float stores decimals. In Python 3, / always returns a float (even 4 / 2 = 2.0). Use // for integer division.


🔀 Control Flow

Q4: What is the difference between break and continue?

Show answer

break exits the loop entirely. continue skips the rest of the current iteration and jumps to the next one.


Q5: What does this code print?

for i in range(3):
    pass
print(i)
Show answer

2 — the loop variable i retains its last value after the loop ends, even with pass.


Q6: What is a list comprehension? Write one that filters and transforms.

Show answer

A compact syntax for building lists. Example: get squares of even numbers from 1–20:

result = [x**2 for x in range(1, 21) if x % 2 == 0]

🔧 Functions

Q7: What is the difference between *args and **kwargs?

Show answer
  • *args collects extra positional arguments into a tuple
  • **kwargs collects extra keyword arguments into a dict
def f(*args, **kwargs):
    print(args)    # (1, 2, 3)
    print(kwargs)  # {'x': 10, 'y': 20}
f(1, 2, 3, x=10, y=20)

Q8: What is a lambda function? Write one that sorts a list of tuples by the second element.

Show answer

An anonymous one-line function.

data = [(1, 'banana'), (2, 'apple'), (3, 'cherry')]
sorted_data = sorted(data, key=lambda x: x[1])
# [(2, 'apple'), (1, 'banana'), (3, 'cherry')]

Q9: What is a mutable default argument trap?

Show answer

Using a mutable object (list, dict) as a default parameter is a classic bug:

# BUG — the list is created once and reused!
def append_to(item, lst=[]):
    lst.append(item)
    return lst

print(append_to(1))   # [1]
print(append_to(2))   # [1, 2]  ← unexpected!

# FIX — use None as default
def append_to(item, lst=None):
    if lst is None:
        lst = []
    lst.append(item)
    return lst

📚 Data Structures

Q10: What is the difference between a list and a tuple?

Show answer
List Tuple
Mutable
Syntax [1,2,3] (1,2,3)
Use case Dynamic data Fixed data, dict keys
Speed Slightly slower Slightly faster

Q11: How do you safely get a value from a dict that might not have the key?

Show answer

Use .get() with a default:

d = {"name": "Alice"}
email = d.get("email", "no email")   # "no email"

Q12: What is the time complexity of in for a list vs a set?

Show answer

List: O(n) — must check every element. Set: O(1) — uses a hash table. For large membership tests, always use a set.


Q13: How do you remove duplicates from a list while preserving order?

Show answer
data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]
unique = list(dict.fromkeys(data))
# [3, 1, 4, 5, 9, 2, 6]

Q14: What is the difference between append() and extend()?

Show answer
a = [1, 2, 3]
a.append([4, 5])     # [1, 2, 3, [4, 5]]  ← adds list as one element

b = [1, 2, 3]
b.extend([4, 5])     # [1, 2, 3, 4, 5]    ← adds each element

🧰 Advanced Python

Q15: What does Python's with statement do? Give a real example.

Show answer

The with statement is a context manager — it guarantees cleanup runs even if an exception occurs inside the block. The object must implement __enter__ and __exit__.

# Without with: file might stay open if read() raises
f = open('data.csv')
content = f.read()
f.close()

# With with: file is always closed, even on error
with open('data.csv') as f:
    content = f.read()
# f is closed here automatically

This pattern applies beyond files — database connections, locks, and temporary directories all use context managers.


Q16: What is a generator? How does it differ from a list?

Show answer

A generator yields values one at a time using yield instead of building the whole sequence in memory. It is lazy — each value is computed only when requested.

# List: all 1 million squares stored in memory at once
squares_list = [i**2 for i in range(1_000_000)]

# Generator: computes one value at a time
def squares(n):
    for i in range(n):
        yield i**2

gen = squares(1_000_000)
print(next(gen))   # 0
print(next(gen))   # 1

Use generators when the sequence is large and you only need one value at a time — for example, streaming rows from a large CSV file.


Q17: What is the difference between deepcopy and a regular assignment in Python?

Show answer

Assignment creates another reference to the same object. Modifying one modifies both. deepcopy creates a fully independent copy — nested structures are copied recursively.

import copy

original = [[1, 2], [3, 4]]

# Assignment — same object
ref = original
ref[0][0] = 99
print(original)   # [[99, 2], [3, 4]] ← original changed!

# Deepcopy — independent copy
original = [[1, 2], [3, 4]]
clone = copy.deepcopy(original)
clone[0][0] = 99
print(original)   # [[1, 2], [3, 4]] ← original unchanged

This matters for nested structures like lists of lists, dictionaries of lists, or any mutable container inside another.


Q18: Explain the GIL. Why does it matter for data science?

Show answer

The Global Interpreter Lock (GIL) is a mutex in CPython that allows only one thread to execute Python bytecode at a time. This means multi-threaded Python programs cannot run pure Python code in parallel across CPU cores.

# CPU-bound: threads don't help — use multiprocessing
from multiprocessing import Pool

def train_fold(fold_data):
    # train a model on this fold
    ...

with Pool(processes=4) as pool:
    results = pool.map(train_fold, folds)

# I/O-bound: threads still help (GIL is released while waiting)
import threading

def download(url):
    # network wait releases GIL
    ...

Key rules for data science: - Model training (CPU-bound) — use multiprocessing or joblib - Downloading datasets / API calls (I/O-bound) — threads are fine - NumPy and Pandas release the GIL for C-level operations, so parallelism works there