0% found this document useful (0 votes)
12 views17 pages

Advanced Python Interview Questions Guide

The document is a comprehensive Python Interview Handbook covering advanced topics including core Python concepts, data structures, algorithms, and object-oriented programming. It provides a series of interview questions along with explanations and example code for each topic. Key areas include string manipulation, recursion, data handling, memory profiling, and best practices in Python programming.

Uploaded by

coolwtf30
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views17 pages

Advanced Python Interview Questions Guide

The document is a comprehensive Python Interview Handbook covering advanced topics including core Python concepts, data structures, algorithms, and object-oriented programming. It provides a series of interview questions along with explanations and example code for each topic. Key areas include string manipulation, recursion, data handling, memory profiling, and best practices in Python programming.

Uploaded by

coolwtf30
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Title

Python Interview Handbook — Advanced (Detailed)

Author: ChatGPT
Contents: 1. Core Python Basics
2. Data Structures
3. Functions & Functional Tools
4. OOP
5. File & Exception Handling
6. Decorators & Generators
7. Modules & Packages
8. Algorithms & Problem Solving
9. Tricky & Conceptual Questions

Each entry: Question • Explanation • Example Code

1. Reverse a string (in-place concerns)


Question
Reverse a string. Describe time/space tradeoffs.

Explanation
Python strings are immutable. Common patterns: slicing, reversed(), manual accumulation. Slicing s[::-1] is concise
and O(n) time, O(n) space (creates new string). If "in-place" is required (e.g., list of chars), convert to list and swap.

Code
def reverse_string(s: str) -> str:
# simple and Pythonic
return s[::-1]

def reverse_inplace_list(chars: list) -> None:


# modify list in-place (two-pointer)
l, r = 0, len(chars) - 1
while l < r:
chars[l], chars[r] = chars[r], chars[l]
l += 1
r -= 1

2. Check palindrome (ignore non-alpha and case)


Question
Check if a string is a palindrome, ignoring non-alphanumeric characters and case.

Explanation
Normalize the string: filter alphanumeric and lowercase. Then compare to its reverse. Use two-pointer approach to
reduce allocations.

Code
import re

def is_palindrome(s: str) -> bool:


filtered = [Link](r'[^A-Za-z0-9]', '', s).lower()
return filtered == filtered[::-1]

def is_palindrome_two_pointers(s: str) -> bool:


i, j = 0, len(s) - 1
while i < j:
while i < j and not s[i].isalnum():
i += 1
while i < j and not s[j].isalnum():
j -= 1
if s[i].lower() != s[j].lower():
return False
i += 1
j -= 1
return True

3. Fibonacci — recursion vs DP
Question
Generate nth Fibonacci number — compare naive recursion, memoization, and iterative.

Explanation
Naive recursion is exponential. Memoization or iterative dynamic programming yields O(n) time. Iterative with constant
space is most efficient.

Code
def fib_recursive(n):
if n < 2:
return n
return fib_recursive(n-1) + fib_recursive(n-2)

def fib_memo(n, memo=None):


if memo is None:
memo = {}
if n in memo:
return memo[n]
if n < 2:
return n
memo[n] = fib_memo(n-1, memo) + fib_memo(n-2, memo)
return memo[n]

def fib_iter(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a

4. List vs Tuple vs Array


Question
Explain differences between list and tuple and when to use which.

Explanation
Lists are mutable, tuples are immutable. Tuples can be used as dictionary keys if contents are immutable, and are
slightly faster. Use lists for collections you modify; tuples for fixed collections or when you need hashability.

Code
# Example
lst = [1,2,3]
tpl = (1,2,3)
try:
tpl[0] = 5
except TypeError:
pass

5. Dictionary common patterns (counting, grouping)


Question
Common interview tasks using dict: counting, grouping, frequency map.

Explanation
[Link] and defaultdict simplify implementations. Use dict comprehensions for concise transforms.

Code
from collections import Counter, defaultdict

def freq_count(arr):
return Counter(arr)

def group_by_key(pairs):
d = defaultdict(list)
for k,v in pairs:
d[k].append(v)
return dict(d)

6. Two-sum (hashmap method)


Question
Given array and target, return indices of two numbers summing to target.

Explanation
Single-pass hashmap stores value->index. For each element check if complement exists.

Code
def two_sum(nums, target):
seen = {}
for i, n in enumerate(nums):
comp = target - n
if comp in seen:
return [seen[comp], i]
seen[n] = i
return None

7. Sliding window (max sum subarray of size k)


Question
Find maximum sum subarray of fixed size k.

Explanation
Use sliding window to maintain current sum in O(n).

Code
def max_subarray_sum_k(arr, k):
if k > len(arr): return None
window_sum = sum(arr[:k])
max_sum = window_sum
for i in range(k, len(arr)):
window_sum += arr[i] - arr[i-k]
max_sum = max(max_sum, window_sum)
return max_sum

8. Merge two sorted lists


Question
Merge two sorted lists into one sorted list.

Explanation
Classic two-pointer merge O(n+m).

Code
def merge_sorted(a, b):
i=j=0
res = []
while i < len(a) and j < len(b):
if a[i] <= b[j]:
[Link](a[i]); i += 1
else:
[Link](b[j]); j += 1
[Link](a[i:]); [Link](b[j:])
return res

9. Binary search (iterative & recursive)


Question
Implement binary search.

Explanation
Works on sorted arrays. Be careful with mid calculation for large indices (use low + (high-low)//2).

Code
def binary_search_iter(arr, x):
low, high = 0, len(arr)-1
while low <= high:
mid = low + (high-low)//2
if arr[mid] == x:
return mid
elif arr[mid] < x:
low = mid + 1
else:
high = mid - 1
return -1

def binary_search_rec(arr, x, low=0, high=None):


if high is None: high = len(arr)-1
if low > high: return -1
mid = low + (high-low)//2
if arr[mid] == x: return mid
if arr[mid] < x: return binary_search_rec(arr, x, mid+1, high)
return binary_search_rec(arr, x, low, mid-1)

10. Time complexity basics


Question
Explain Big-O for common operations: list append, pop, dict lookup, set add.

Explanation
- [Link]: amortized O(1)
- [Link](): O(1) at end, O(n) at start
- dict/set lookup/insert/delete: average O(1), worst-case O(n) (rare with good hash)
- sorting: O(n log n)

Code
# No code — conceptual.

11. OOP: Class, Inheritance, Polymorphism


Question
Explain class basics, inheritance, method overriding, and polymorphism.

Explanation
Use base classes, derived classes, and override methods. Polymorphism: functions can operate on objects of
different types if they implement the required interface.

Code
class Animal:
def speak(self):
raise NotImplementedError

class Dog(Animal):
def speak(self):
return "woof"

class Cat(Animal):
def speak(self):
return "meow"

def animal_sound(a: Animal):


return [Link]()

# Usage
dog = Dog(); cat = Cat()

12. Encapsulation & @property


Question
How to enforce encapsulation and use property for getters/setters.

Explanation
Use leading underscore for private attributes and @property decorator for controlled access.

Code
class Person:
def __init__(self, name):
self._name = name

@property
def name(self):
return self._name

@[Link]
def name(self, value):
if not value:
raise ValueError("Name cannot be empty")
self._name = value

13. Dunder methods and operator overloading


Question
Explain __str__, __repr__, __eq__, __lt__.

Explanation
Dunder methods allow customizing behavior of objects for printing, comparison, hashing, etc.

Code
class Box:
def __init__(self, vol):
[Link] = vol
def __repr__(self): return f"Box({[Link]})"
def __eq__(self, other): return isinstance(other, Box) and [Link] == [Link]

14. Generators & yield


Question
Explain generators and memory benefits.

Explanation
Generators produce values lazily, useful for streaming large sequences. Use yield to create generator functions.

Code
def gen_count(n):
i=0
while i < n:
yield i
i += 1

for x in gen_count(5):
pass

15. Decorators (function decorators)


Question
What are decorators? Write a timing decorator.

Explanation
Decorators wrap functions to add behavior. Use [Link] to preserve metadata.
Code
import time
from functools import wraps

def timing(f):
@wraps(f)
def wrapped(*args, **kwargs):
t0 = [Link]()
res = f(*args, **kwargs)
t1 = [Link]()
print(f"{f.__name__} took {t1-t0:.6f}s")
return res
return wrapped

@timing
def compute(n):
s=0
for i in range(n):
s += i
return s

16. Context managers & with-statement


Question
Implement a custom context manager.

Explanation
Use __enter__/__exit__ methods or [Link]. Ensures resource cleanup.

Code
class MyCtx:
def __enter__(self):
print("enter")
return "resource"
def __exit__(self, exc_type, exc, tb):
print("exit")
return False

with MyCtx() as r:
pass

# using contextlib
from contextlib import contextmanager

@contextmanager
def my_ctx():
try:
yield "res"
finally:
pass

17. Iterators protocol


Question
Explain iterator protocol: __iter__ and __next__.
Explanation
Iterable must implement __iter__ returning an iterator with __next__.

Code
class Count:
def __init__(self, n):
self.n = n
self.i = 0
def __iter__(self): return self
def __next__(self):
if self.i >= self.n:
raise StopIteration
v = self.i
self.i += 1
return v

18. Closures
Question
Explain closures and give an example.

Explanation
Closure: inner function remembers variables from enclosing scope. Useful for factory functions or data hiding.

Code
def make_multiplier(n):
def mul(x):
return x * n
return mul

double = make_multiplier(2)
print(double(5)) # 10

19. Mutable default args pitfall


Question
Why avoid mutable default args?

Explanation
Default args evaluated once at function definition; using a list will share it across calls.

Code
def append_bad(x, lst=[]):
[Link](x)
return lst

def append_good(x, lst=None):


if lst is None:
lst = []
[Link](x)
return lst
20. Threading vs Multiprocessing
Question
When to use threading and multiprocessing in Python?

Explanation
CPython has GIL blocking true parallelism for CPU-bound tasks; use multiprocessing for CPU-bound; threading for
IO-bound tasks. Be careful with shared state; use queues or [Link].

Code
import threading, multiprocessing, time

def work(i):
[Link](0.1)

# examples omitted for brevity

21. File read/write patterns


Question
Best practices for reading and writing files.

Explanation
Use with-statement to ensure closure. For large files iterate line-by-line.

Code
def count_lines(path):
with open(path, 'r', encoding='utf-8') as f:
return sum(1 for _ in f)

22. Exception hierarchy and custom exceptions


Question
Create and raise custom exceptions.

Explanation
Inherit from Exception. Use specific exceptions and avoid catching broad Exception unless necessary.

Code
class MyError(Exception):
pass

def f(x):
if x < 0:
raise MyError("negative")

23. Unit testing with pytest/unittest


Question
Write a simple unit test.

Explanation
Use pytest for concise tests or unittest for compatibility.

Code
# Using pytest style
def add(a,b): return a+b

def test_add():
assert add(2,3) == 5

24. JSON & serialization


Question
Serialize and deserialize objects to JSON.

Explanation
Use json module. For custom objects supply default= or implement __dict__ transforms.

Code
import json
class P:
def __init__(self,x):
self.x=x
p = P(3)
s = [Link](p.__dict__)
obj = [Link](s)

25. CSV handling and streaming large CSVs


Question
Efficient CSV processing.

Explanation
Use csv module or pandas for complex tasks; for streaming use [Link] iteratively.

Code
import csv
def stream_csv(path):
with open(path, newline='') as f:
reader = [Link](f)
for row in reader:
yield row

26. Memory profiling basics


Question
How to profile memory usage.

Explanation
Use modules like tracemalloc, memory_profiler to identify leaks.

Code
import tracemalloc
[Link]()
# run code
snapshot = tracemalloc.take_snapshot()
top_stats = [Link]('lineno')
print(top_stats[:5])
27. Performance: list vs deque
Question
When to use [Link].

Explanation
deque provides O(1) append/pop from both ends. Lists are fine for random access and append/pop at end.

Code
from collections import deque
d = deque()
[Link](1)

28. Hashing and __hash__


Question
How to make a class hashable.

Explanation
Define __hash__ and __eq__. Immutable fields recommended. If __eq__ defined, to keep hashability implement
__hash__ or set __hash__=None to make unhashable.

Code
class Point:
def __init__(self,x,y): self.x=x; self.y=y
def __eq__(self,other): return isinstance(other,Point) and self.x==other.x and self.y==other.y
def __hash__(self): return hash((self.x,self.y))

29. Serialization with pickle vs json


Question
Difference between pickle and json.

Explanation
pickle can serialize arbitrary Python objects (not safe for untrusted sources). JSON is text-based and
language-agnostic but supports basic types only.

Code
import pickle, json
data = {'a':1}
[Link](data)
[Link](data)

30. Virtual environments & packaging basics


Question
Why venv and how to make a package.

Explanation
Use venv/virtualenv to isolate dependencies. Create [Link]/[Link] for packaging. Use pip install -e . for
editable installs.

Code
# conceptual — no code

31. Reverse linked list (iterative & recursive)


Question
Reverse a singly linked list.

Explanation
Iterative approach uses three pointers prev, curr, next. Recursive approach rewires links during unwinding.

Code
class Node:
def __init__(self,v, nxt=None):
self.v=v; [Link]=nxt

def reverse_iter(head):
prev = None
curr = head
while curr:
nxt = [Link]
[Link] = prev
prev = curr
curr = nxt
return prev

def reverse_rec(head):
if not head or not [Link]:
return head
p = reverse_rec([Link])
[Link] = head
[Link] = None
return p

32. Detect cycle in linked list (Floyd's)


Question
Detect cycle and find cycle start.

Explanation
Use slow and fast pointers to detect cycle. To find start, move one pointer to head and step both until they meet.

Code
def detect_cycle(head):
slow = fast = head
while fast and [Link]:
slow = [Link]
fast = [Link]
if slow == fast:
# find start
ptr = head
while ptr != slow:
ptr = [Link]
slow = [Link]
return ptr
return None
33. Top K elements (heap)
Question
Find k largest elements.

Explanation
Use min-heap of size k or [Link].

Code
import heapq
def k_largest(nums, k):
return [Link](k, nums)

34. Merge intervals


Question
Given intervals merge overlapping ones.

Explanation
Sort by start time and merge sequentially.

Code
def merge_intervals(intervals):
if not intervals: return []
[Link](key=lambda x: x[0])
merged = [intervals[0]]
for s,e in intervals[1:]:
last_s, last_e = merged[-1]
if s <= last_e:
merged[-1] = (last_s, max(last_e, e))
else:
[Link]((s,e))
return merged

35. Longest increasing subsequence (LIS) — n log n


Question
Find length of LIS in O(n log n).

Explanation
Use patience sorting with tails array and binary search.

Code
import bisect
def lis_length(nums):
tails = []
for x in nums:
i = bisect.bisect_left(tails, x)
if i == len(tails):
[Link](x)
else:
tails[i] = x
return len(tails)
36. Graph traversal: BFS and shortest path (unweighted)
Question
Use BFS for shortest path in unweighted graphs.

Explanation
BFS from source records distances and parents.

Code
from collections import deque
def bfs_shortest_path(graph, start, goal):
q = deque([start])
visited = {start}
parent = {start: None}
while q:
node = [Link]()
if node == goal:
path=[]
cur=node
while cur:
[Link](cur)
cur=parent[cur]
return path[::-1]
for nei in [Link](node, []):
if nei not in visited:
[Link](nei)
parent[nei]=node
[Link](nei)
return None

37. Dynamic programming example: knapsack (0/1)


Question
0/1 knapsack DP.

Explanation
Use DP table or optimized 1D DP.

Code
def knapsack(values, weights, W):
n = len(values)
dp = [0] * (W+1)
for i in range(n):
for w in range(W, weights[i]-1, -1):
dp[w] = max(dp[w], dp[w-weights[i]] + values[i])
return dp[W]

38. Backtracking example: N-Queens


Question
Place N queens.

Explanation
Use recursion with pruning (cols, diag1, diag2 sets).

Code
def solve_nq(n):
res=[]
cols=set(); d1=set(); d2=set()
board=[["."]*n for _ in range(n)]
def back(r):
if r==n:
[Link](["".join(row) for row in board])
return
for c in range(n):
if c in cols or (r-c) in d1 or (r+c) in d2:
continue
[Link](c); [Link](r-c); [Link](r+c); board[r][c]="Q"
back(r+1)
[Link](c); [Link](r-c); [Link](r+c); board[r][c]="."
back(0); return res

39. String pattern matching: KMP basics


Question
Explain KMP and build LPS array.

Explanation
KMP builds longest prefix-suffix (lps) to skip comparisons.

Code
def build_lps(pat):
lps=[0]*len(pat)
length=0; i=1
while i < len(pat):
if pat[i]==pat[length]:
length+=1; lps[i]=length; i+=1
else:
if length: length = lps[length-1]
else: lps[i]=0; i+=1
return lps

40. System design interview basics (python services)


Question
Design considerations for Python services (scalability, state, APIs).

Explanation
Stateless services scale better; use WSGI/ASGI servers, caching (Redis), background workers (Celery), database
sharding, health checks, metrics.

Code
# conceptual - no runnable code

41. GIL implications and async IO


Question
Explain GIL and async vs threading.

Explanation
GIL prevents multiple native Python bytecodes executing in parallel in CPython. Use multiprocessing for CPU
parallelism and async/await (asyncio) for scalable IO concurrency.

Code
import asyncio
async def say(x):
await [Link](1)
return x

42. Monkey patching and pros/cons


Question
What is monkey patching; when to use.

Explanation
Monkey patching modifies modules/classes at runtime—powerful for testing or hotfixes but risky for maintainability.

Code
import math
[Link] = lambda x: 0 # dangerous; don't do in prod

43. Time and space tradeoffs; big O revisited


Question
Explain tradeoffs with examples.

Explanation
Sometimes using extra memory reduces time (memoization). Streaming trades memory for repeated passes. Choose
technique based on constraints.

Code
# conceptual

44. Security: pickling untrusted data


Question
Why not unpickle untrusted data.

Explanation
pickle can execute arbitrary code during unpickling; use json or other safe formats for untrusted sources.

Code
# demonstration omitted for safety

45. Common interview puzzle: find duplicate in array 1..n (space O(1))
Question
Find the duplicate in array of length n+1 with numbers 1..n using O(1) extra space.

Explanation
Use Floyd's cycle detection by treating array indices as next pointers.

Code
def find_duplicate(nums):
tortoise = nums[0]; hare = nums[0]
while True:
tortoise = nums[tortoise]
hare = nums[nums[hare]]
if tortoise == hare:
break
ptr1 = nums[0]
ptr2 = tortoise
while ptr1 != ptr2:
ptr1 = nums[ptr1]
ptr2 = nums[ptr2]
return ptr1

You might also like