Python Interview Handbook
Complete Guide to Ace Your Python Developer Interview
Version 1.0 | December 2025 | 220+ Questions | Interview Ready
Table of Contents
Beginner Level: Core Concepts, Data Types, Control Flow, Strings
Intermediate Level: Functions, Data Structures, File I/O, Libraries
Advanced Level: OOP, Exceptions, Memory, Advanced Concepts
Expert Level: Decorators, Generators, Async, Type Hints, Tricky Questions
⭐ BEGINNER LEVEL
Core Concepts (Q1-10)
Q1: Why is Python called interpreted?
Python is called an interpreted language because it executes code line-by-line at runtime,
without requiring a separate compilation step like C++ or Java. The Python interpreter reads
the source code and converts it directly into executable instructions. When an error occurs,
the interpreter displays the exact line number where the problem happened, making
debugging easier. This approach enables a faster development cycle since you can test code
changes immediately without waiting for compilation.
Key Point: Python uses a two-stage process: source code → bytecode (.pyc files) → CPython
VM execution.
Q2: Is indentation mandatory?
Yes, indentation is absolutely mandatory in Python and is not just a style choice. Unlike
Java or C++ which use curly braces {} to define code blocks, Python uses indentation
(typically 4 spaces per level) to determine the scope and structure of your code. Incorrect
indentation will raise an IndentationError at runtime.
Correct indentation
if True:
print("Indented correctly")
Wrong - will cause IndentationError
if True:
print("Wrong indentation")
Q3: Is Python case sensitive?
Yes, Python is strictly case-sensitive. Variable names, function names, and keywords are all
case-sensitive. For example, x, X, and X are three completely different variables. This applies
to everything: Print is not the same as print, and True is not the same as true.
Q4: What are keywords in Python?
Keywords are reserved words that have special meaning in Python and cannot be used as
variable names. Python has 33 keywords including: False, None, True, and, or, not, def, class,
for, if, else, return, break, continue, pass, import, from, try, except, finally, with, lambda,
yield, global, nonlocal, assert, del, in, is, as, and while.
You can view all keywords using:
import keyword
print([Link])
Q5: What are literals?
Literals are raw, fixed data values written directly in your code. They represent actual
values rather than variables. Types of literals include:
String literals: "hello", 'world', """multi-line"""
Numeric literals: 42 (int), 3.14 (float), 2+3j (complex)
Boolean literals: True, False
Special literal: None
Q6: Is Python compiled or interpreted?
Python is actually both. Python source code is first compiled into bytecode (.pyc files stored
in __pycache__ directories), which is platform-independent. This bytecode is then
interpreted by the Python Virtual Machine (CPython) at runtime. This hybrid approach
gives Python the advantage of fast development (no separate compilation step) while still
benefiting from some compilation optimizations.
Q7: Key features of Python
Python's popularity stems from several key features:
Free and Open Source: Cost-free with transparent, modifiable source code
Simple, readable syntax: Resembles English, making it easy to learn and maintain
Interpreted execution: No separate compilation; run code immediately
Object-Oriented support: Full OOP capabilities alongside procedural programming
Cross-platform compatibility: Runs on Windows, macOS, Linux, etc.
Extensive ecosystem: Massive library collection (NumPy, Pandas, Django, Flask,
etc.)
Dynamic typing: Variables can hold any type of data
Automatic memory management: Garbage collection handles memory cleanup
Q8: What is PEP8?
PEP 8 (Python Enhancement Proposal 8) is the official style guide for Python code. It
provides conventions for writing clean, readable Python code. Key PEP 8 guidelines include:
Use 4-space indentation (not tabs)
Use snake_case for variables and functions: my_variable
Use PascalCase for class names: MyClass
Maximum line length of 79 characters for code, 72 for comments
Use two blank lines between top-level function/class definitions
Use one blank line between method definitions inside a class
Add meaningful comments explaining the "why", not the "what"
Following PEP 8 makes your code more professional and easier for others (and your future
self) to understand.
Q9: How to add comments?
Python supports two types of comments:
Single-line comments start with #:
This is a single-line comment
x = 5 # Inline comment
Multi-line comments use triple quotes (docstrings):
"""
This is a multi-line comment.
It can span multiple lines.
Often used for function/class documentation.
"""
def my_function():
"""This is a docstring for the function."""
pass
Docstrings are accessible via function.__doc__ and are convention for documenting
modules, classes, and functions.
Q10: What is the pass statement?
The pass statement is a null operation that does nothing when executed. It's used as a
placeholder when a statement is syntactically required (like in function definitions or
loops) but no action needs to be taken yet. This is useful during development when you're
sketching out code structure.
def empty_function():
pass # Placeholder - implement later
class EmptyClass:
pass
if condition:
pass # Don't do anything yet
Data Types (Q11-25)
Q11: Built-in data types in Python
Python provides these fundamental data types:
• Numeric: int (integers), float (decimal numbers), complex (a+bj format)
• Sequence: str (strings), list (ordered, mutable), tuple (ordered, immutable)
• Mapping: dict (key-value pairs)
• Set: set (unordered unique elements)
• Boolean: bool (True/False)
• Special: NoneType (None value)
Q12: Mutable vs Immutable data types
Aspect Mutable Immutable
Can be changed after Cannot be changed after
Definition
creation creation
Operations create new
Modification Changes happen in-place
objects
Less efficient for large
Memory More efficient
data
Examples list, dict, set int, float, str, tuple, frozenset
Hashable No (cannot be dict keys) Yes (can be dict keys)
Table 1: Mutable vs Immutable Comparison
Example:
Immutable - creates new object
x = "hello"
y = [Link]() # New string created
Mutable - changes in place
lst = [1, 2, 3]
[Link](4) # Same list object modified
Q13: List vs Tuple comparison
Feature List Tuple
Mutable Yes No
Syntax [] ()
Speed Slower Faster iteration
Memory Higher Lower
Use Case Dynamic, changing data Fixed, constant data
Hashable No Yes (if immutable contents)
Table 2: List vs Tuple Detailed Comparison
When to use:
Lists: When you need to modify data (add, remove, change elements)
Tuples: For immutable data, as dictionary keys, or function return values with
multiple values
Q14: What are Python sets?
Sets are unordered collections of unique elements. They are mutable but don't support
indexing. Sets automatically eliminate duplicate values and are optimized for fast
membership testing.
Creating a set
my_set = {1, 2, 2, 3} # Duplicates removed
print(my_set) # {1, 2, 3}
Membership testing (very fast)
if 1 in my_set:
print("1 is in the set")
Set operations
set_a = {1, 2, 3}
set_b = {3, 4, 5}
print(set_a & set_b) # Intersection: {3}
print(set_a | set_b) # Union: {1,2,3,4,5}
print(set_a - set_b) # Difference: {1,2}
Key characteristics: Unordered, mutable, no duplicates, no indexing, fast membership
testing.
Q15: What is a Dictionary?
Dictionaries are unordered collections of key-value pairs (as of Python 3.7, they maintain
insertion order). Keys must be immutable (hashable) data types like strings, numbers, or
tuples. Dictionaries are mutable and offer efficient data lookup.
Creating a dictionary
person = {
'name': 'John',
'age': 30,
'city': 'New York'
}
Accessing values
print(person['name']) # 'John'
Modifying
person['age'] = 31
Adding new key-value
person['email'] = 'john@[Link]'
Dictionary methods
[Link]() # All keys
[Link]() # All values
[Link]() # Key-value pairs
Q16: How to check data type
Use the type() function to determine the data type of any object:
print(type(42)) # <class 'int'>
print(type(3.14)) # <class 'float'>
print(type("hello")) # <class 'str'>
print(type([1, 2, 3])) # <class 'list'>
print(type({'a': 1})) # <class 'dict'>
print(type((1, 2))) # <class 'tuple'>
For more detailed type checking
isinstance(42, int) # True
isinstance("text", (int, str)) # True
Q17: Type conversion functions
Python provides built-in functions to convert between data types:
Convert to int
int("42") # 42
int(3.99) # 3 (truncates, doesn't round)
int(True) # 1
Convert to float
float("3.14") # 3.14
float(42) # 42.0
Convert to string
str(42) # "42"
str([1, 2, 3]) # "[1, 2, 3]"
Convert to list
list("abc") # ['a', 'b', 'c']
list((1, 2, 3)) # [1, 2, 3]
Convert to tuple
tuple([1, 2, 3]) # (1, 2, 3)
Convert to set
set([1, 2, 2, 3]) # {1, 2, 3}
Convert to dict
dict([('a', 1), ('b', 2)]) # {'a': 1, 'b': 2}
Control Flow (Q26-40)
Q26: Comparison operators
Comparison operators return Boolean values (True or False) and are used in conditional
statements:
• == - Equal to: 5 == 5 → True
• != - Not equal to: 5 != 3 → True
• < - Less than: 3 < 5 → True
• > - Greater than: 5 > 3 → True
• <= - Less than or equal: 5 <= 5 → True
• >= - Greater than or equal: 5 >= 3 → True
Important: Use == for comparison, not = (which is assignment).
Q27: Logical operators
Logical operators combine Boolean expressions:
and: Returns True if both conditions are true
age > 18 and has_license # Both must be True
or: Returns True if at least one condition is true
is_weekend or is_holiday # At least one is True
not: Reverses the Boolean value
not is_raining # True if not raining
Q28: break vs continue
break: Immediately exits/terminates the entire loop
for i in range(10):
if i == 5:
break # Exits loop when i is 5
continue: Skips the current iteration and continues with the next one
for i in range(10):
if i == 5:
continue # Skips iteration when i is 5, continues with i=6
Q29: for vs while loop
for loop: Iterates over a sequence (list, tuple, string, range) a specific number of
times
for i in range(5):
print(i) # 0, 1, 2, 3, 4
for item in [1, 2, 3]:
print(item)
while loop: Repeats as long as a condition is true, useful when iteration count is
unknown
count = 0
while count < 5:
print(count)
count += 1
Q30: Indexing and slicing
Indexing accesses individual elements using their position:
lst = ['a', 'b', 'c', 'd', 'e']
print(lst[0]) # 'a' - first element
print(lst[-1]) # 'e' - last element
print(lst[-2]) # 'd' - second from last
Slicing extracts a portion of a sequence using start:end:step:
lst[1:4] # ['b', 'c', 'd'] - elements at index 1, 2, 3
lst[:3] # ['a', 'b', 'c'] - first 3 elements
lst[::2] # ['a', 'c', 'e'] - every 2nd element
lst[::-1] # ['e', 'd', 'c', 'b', 'a'] - reversed
Q31: What is slicing syntax?
The slicing syntax is: sequence[start:end:step]
start: Starting index (inclusive), defaults to 0
end: Ending index (exclusive), defaults to length
step: Increment between indices, defaults to 1
s = "Python"
print(s[1:4]) # 'yth' (indices 1, 2, 3)
print(s[::2]) # 'Pto' (every 2nd character)
print(s[::-1]) # 'nohtyP' (reversed)
Q32: Negative indexing
Negative indices count from the end of the sequence, starting at -1:
lst = ['a', 'b', 'c', 'd', 'e']
lst[-1] # 'e' - last element
lst[-2] # 'd' - second-to-last
lst[-5] # 'a' - first element
lst[-3:] # ['c', 'd', 'e'] - last 3 elements
lst[:-2] # ['a', 'b', 'c'] - all except last 2
Strings (Q41-50)
Q41: Common string methods
Strings provide many useful methods for manipulation:
Case conversion
"hello".upper() # "HELLO"
"HELLO".lower() # "hello"
"hello world".title() # "Hello World"
"hello world".capitalize() # "Hello world"
Searching and testing
"hello".startswith("he") # True
"hello".endswith("lo") # True
"hello".find("ll") # 2 (index of first occurrence)
"hello".count("l") # 2 (number of occurrences)
Splitting and joining
"hello world".split() # ['hello', 'world']
"-".join(['a', 'b', 'c']) # 'a-b-c'
Whitespace removal
" hello ".strip() # "hello"
" hello ".lstrip() # "hello " (left only)
" hello ".rstrip() # " hello" (right only)
Replacement
"hello world".replace("world", "Python") # "hello Python"
Q42: Check if substring exists
Multiple approaches to check if a substring exists:
Using 'in' operator (most Pythonic)
if 'world' in 'hello world':
print("Found!")
Using startswith()
'hello world'.startswith('hello') # True
Using endswith()
'hello world'.endswith('world') # True
Using find() - returns index or -1
if 'world' in 'hello world':
index = 'hello world'.find('world') # 6
Q43: Remove whitespace
Remove from both ends
" hello ".strip() # "hello"
Remove from left side
" hello ".lstrip() # "hello "
Remove from right side
" hello ".rstrip() # " hello"
Remove ALL spaces
"hello world".replace(" ", "") # "helloworld"
Remove leading/trailing of specific
character
"xxxhelloxxx".strip("x") # "hello"
Q44: Count character occurrences
text = "hello world"
Count specific character
[Link]('l') # 3
Count substring
[Link]('lo') # 1
Case-insensitive counting
[Link]().count('o') # 2
Q45: Reverse a string
Using slicing (most common)
"hello"[::-1] # "olleh"
Using reversed() function
''.join(reversed("hello")) # "olleh"
Using loop
result = ""
for char in "hello":
result = char + result # "olleh"
⭐⭐ INTERMEDIATE LEVEL
Functions (Q61-75)
Q61: What are functions?
Functions are reusable blocks of code that perform specific tasks. They help organize code,
improve readability, and eliminate repetition.
Define a function
def greet(name):
"""This function greets someone."""
message = f"Hello, {name}!"
return message
Call the function
result = greet("Alice") # "Hello, Alice!"
Types of functions
1. Built-in functions: print(), len(), range(),
etc.
2. User-defined functions: functions you
create
3. Methods: functions belonging to objects
Function components: definition name, parameters, body, return statement.
Q62: Lambda functions
Lambda functions are small, anonymous functions defined in one line using the lambda
keyword. They're useful for simple operations and are often used with higher-order
functions like map(), filter(), and sorted().
Simple lambda
square = lambda x: x ** 2
print(square(5)) # 25
With multiple parameters
add = lambda x, y: x + y
print(add(3, 4)) # 7
Common use cases
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers)) # [1, 4, 9, 16, 25]
Filter even numbers
evens = list(filter(lambda x: x % 2 == 0, numbers)) # [2, 4]
Sort by second element
pairs = [(1, 'a'), (3, 'c'), (2, 'b')]
sorted(pairs, key=lambda x: x[1]) # [(1, 'a'), (2, 'b'), (3, 'c')]
Q63: *args and **kwargs
These allow functions to accept variable numbers of arguments.
*args (non-keyword arguments): Captures positional arguments as a tuple
def func(*args):
for arg in args:
print(arg)
func(1, 2, 3) # Prints 1, 2, 3
Unpacking with *args
def func(a, b, c):
return a + b + c
numbers = [1, 2, 3]
result = func(*numbers) # Unpacks list into arguments
**kwargs (keyword arguments): Captures keyword arguments as a dictionary
def func(**kwargs):
for key, value in [Link]():
print(f"{key}: {value}")
func(name="John", age=30) # Prints name: John, age: 30
Using both together
def func(*args, **kwargs):
print("Positional:", args)
print("Keyword:", kwargs)
func(1, 2, 3, name="John", age=30)
Q64: Default argument pitfall
A common mistake when using mutable default arguments:
❌ WRONG - Dangerous! All calls share the
SAME list
def bad(items=[]):
[Link]("new")
return items
bad() # ['new']
bad() # ['new', 'new'] - list persists!
✅ CORRECT - Use None as default
def good(items=None):
if items is None:
items = []
[Link]("new")
return items
good() # ['new']
good() # ['new'] - fresh list each time
Why: Default arguments are evaluated once at function definition, not at each call.
Mutable objects (list, dict, set) persist between calls.
Q65: Docstrings
Docstrings are string literals that document what a function/class/module does. They
appear immediately after the definition and can span multiple lines.
def calculate_area(radius):
"""
Calculate the area of a circle.
Args:
radius (float): The radius of the circle
Returns:
float: The area of the circle
Example:
>>> calculate_area(5)
78.53981633974483
"""
return 3.14159 * radius ** 2
Access docstring
print(calculate_area.doc)
Auto-generate documentation with help()
help(calculate_area)
Docstring conventions (PEP 257):
Start with a short one-line description
Follow with a blank line
Add detailed explanation if needed
Include parameter descriptions (Args)
Include return value description (Returns)
Q66: First-class functions
Functions in Python are first-class objects, meaning they can be:
Assigned to variables
Passed as arguments to other functions
Returned from functions
Stored in data structures
Assign to variable
def greet():
return "Hello"
say_hello = greet
print(say_hello()) # "Hello"
Pass as argument (Higher-order function)
def apply_twice(func, x):
return func(func(x))
def add_one(x):
return x + 1
result = apply_twice(add_one, 5) # (5+1)+1 = 7
Return from function (Closure)
def multiplier(n):
def multiply(x):
return x * n
return multiply
times_three = multiplier(3)
print(times_three(5)) # 15
Data Structures (Q76-90)
Q67: List comprehensions
List comprehensions provide a concise way to create lists. They're faster and more
Pythonic than using loops.
Basic syntax: [expression for item in
sequence]
squares = [x**2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
With condition
evens = [x for x in range(10) if x % 2 == 0]
[0, 2, 4, 6, 8]
Nested loops
pairs = [(x, y) for x in [1,2] for y in ['a','b']]
[(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
String processing
words = ["hello", "world"]
upper_words = [[Link]() for word in words]
['HELLO', 'WORLD']
Complex expressions
results = [x*2 if x % 2 == 0 else x for x in range(5)]
[0, 1, 4, 3, 8]
Q68: Flatten nested lists
Using list comprehension (most Pythonic)
nested = [[1, 2, 3], [4, 5], [6, 7, 8]]
flat = [item for sublist in nested for item in sublist]
[1, 2, 3, 4, 5, 6, 7, 8]
Using itertools
import itertools
flat = list([Link](*nested))
Using sum()
flat = sum(nested, []) # Less efficient for large lists
Recursive approach for deeply nested lists
def flatten(lst):
result = []
for item in lst:
if isinstance(item, list):
[Link](flatten(item))
else:
[Link](item)
return result
Q69: Remove duplicates while preserving order
Using [Link]() (Python 3.7+,
preserves insertion order)
my_list = [1, 2, 2, 3, 1, 4, 2]
unique = list([Link](my_list))
[1, 2, 3, 4]
Using set (loses order)
unique = list(set(my_list))
[1, 2, 3, 4] - order may vary
Using loop (preserves order, slower)
unique = []
for item in my_list:
if item not in unique:
[Link](item)
Performance comparison
[Link]() → O(n) - fastest
set() → O(n) - loses order
loop → O(n²) - slowest
Q70: Tuple concatenation
Using + operator
tuple1 = (1, 2, 3)
tuple2 = (4, 5)
result = tuple1 + tuple2
(1, 2, 3, 4, 5)
Create tuples from separate items
combined = tuple1 + (6,) # Remember the comma!
(1, 2, 3, 6)
Multiple concatenations
result = (1,) + (2,) + (3,) + (4,)
(1, 2, 3, 4)
Performance note: Concatenation creates a
new tuple
Q71: zip() function
zip() combines multiple sequences element-wise, creating an iterator of tuples:
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
Zip together
result = list(zip(names, ages))
[('Alice', 25), ('Bob', 30), ('Charlie', 35)]
With more than 2 sequences
cities = ['NYC', 'LA', 'Chicago']
result = list(zip(names, ages, cities))
[('Alice', 25, 'NYC'), ('Bob', 30, 'LA'),
('Charlie', 35, 'Chicago')]
Unzip (reverse operation)
names, ages = zip(*result)
('Alice', 'Bob', 'Charlie'), (25, 30, 35)
Dictionary creation
data = dict(zip(names, ages))
{'Alice': 25, 'Bob': 30, 'Charlie': 35}
Stops at shortest sequence
list(zip([1,2,3], ['a','b']))
[(1, 'a'), (2, 'b')]
Q72: Most efficient way to get unique elements
my_list = [1, 2, 2, 3, 1, 4, 2, 5]
Option 1: set() - Fastest, loses order
unique = set(my_list) # {1, 2, 3, 4, 5}
Time: O(n) | Space: O(n)
Option 2: [Link]() - Fast, preserves
order (Python 3.7+)
unique = list([Link](my_list)) # [1, 2, 3, 4, 5]
Time: O(n) | Space: O(n)
Option 3: Manual loop - Slow, preserves
order
unique = []
for item in my_list:
if item not in unique:
[Link](item)
Time: O(n²) | Space: O(n)
Recommendation: Use set() for
performance, [Link]() if order
matters
File I/O (Q91-100)
Q91: File processing modes
'r' - Read mode (default)
Opens existing file, cannot write
Raises FileNotFoundError if file doesn't
exist
with open('[Link]', 'r') as f:
content = [Link]()
'w' - Write mode
Creates new file or overwrites existing
Deletes previous content
with open('[Link]', 'w') as f:
[Link]("New content")
'a' - Append mode
Adds content to end of file
Creates file if it doesn't exist
with open('[Link]', 'a') as f:
[Link]("\nAdditional content")
'x' - Exclusive creation mode
Creates new file, raises FileExistsError if
exists
'rb', 'wb' - Binary read/write
For images, PDFs, executables
with open('[Link]', 'rb') as f:
binary_data = [Link]()
'r+' - Read and write
Can both read and write without
truncating
'+' modes: 'r+', 'w+', 'a+'
Allow both reading and writing
Q92: Context manager (with statement)
The with statement automatically manages file opening and closing, ensuring files are
properly closed even if errors occur:
Without context manager (not
recommended)
f = open('[Link]', 'r')
content = [Link]()
[Link]() # Might not execute if error occurs
With context manager (recommended)
with open('[Link]', 'r') as f:
content = [Link]() # File auto-closes after this block
Multiple files
with open('[Link]', 'r') as in_f, open('[Link]', 'w') as out_f:
content = in_f.read()
out_f.write([Link]())
# Both files auto-close
Benefits:
- Cleaner code
- Automatic resource cleanup
- Exception-safe (closes even if error
occurs)
Q93: Pickling and Unpickling
Pickling converts Python objects into a byte stream for storage or transmission. Unpickling
reconstructs the object:
import pickle
Pickling - serialize object to bytes
data = {'name': 'John', 'age': 30}
Save to file
with open('[Link]', 'wb') as f:
[Link](data, f)
Or get bytes directly
pickled = [Link](data)
Unpickling - deserialize bytes to object
with open('[Link]', 'rb') as f:
loaded_data = [Link](f)
Or from bytes
loaded_data = [Link](pickled)
Can pickle any Python object
class Person:
def init(self, name):
[Link] = name
person = Person("Alice")
with open('[Link]', 'wb') as f:
[Link](person, f)
Q94: Delete a file
import os
Delete single file
[Link]('[Link]')
Check if file exists before deleting
if [Link]('[Link]'):
[Link]('[Link]')
Delete directory (empty only)
[Link]('empty_folder')
Delete directory and all contents
import shutil
[Link]('folder_with_contents')
Exception handling
try:
[Link]('[Link]')
except FileNotFoundError:
print("File not found")
except PermissionError:
print("Don't have permission to delete")
Q95: Read CSV to DataFrame
import pandas as pd
Basic reading
df = pd.read_csv('[Link]')
Common parameters
df = pd.read_csv(
'[Link]',
sep=',', # Separator (default is comma)
header=0, # Row number for column names
index_col=0, # Use first column as index
nrows=100, # Read only first 100 rows
skiprows=1, # Skip first row
dtype={'age': int} # Specify column types
)
Read CSV as string
with open('[Link]', 'r') as f:
for line in f:
print([Link]())
Use StringIO for CSV from strings
from io import StringIO
csv_string = "name,age\nJohn,30\nAlice,25"
df = pd.read_csv(StringIO(csv_string))
Libraries (Q101-120)
Q101: What is Pandas?
Pandas is a powerful Python library for data analysis and manipulation. It provides two
main data structures:
Series: 1D labeled array (like a column in a spreadsheet)
DataFrame: 2D table with labeled rows and columns (like a spreadsheet or SQL
table)
import pandas as pd
Create Series
series = [Link]([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
Create DataFrame
df = [Link]({
'Name': ['John', 'Alice', 'Bob'],
'Age': [25, 30, 35],
'City': ['NYC', 'LA', 'Chicago']
})
Common operations
[Link]() # First 5 rows
[Link]() # Statistical summary
df['Name'] # Access column
[Link][0] # Access row by label
[Link][0] # Access row by position
Pandas advantages: Handles missing data, flexible reshaping, efficient computation,
integrates with visualization libraries.
Q102: Create DataFrame from lists
import pandas as pd
From dictionary of lists
df = [Link]({
'cars': ['BMW', 'Audi', 'Mercedes'],
'bikes': ['KTM', 'Pulsar', 'Harley']
})
From list of lists
data = [
['BMW', 'KTM'],
['Audi', 'Pulsar'],
['Mercedes', 'Harley']
]
df = [Link](data, columns=['cars', 'bikes'])
From list of dictionaries
data = [
{'cars': 'BMW', 'bikes': 'KTM'},
{'cars': 'Audi', 'bikes': 'Pulsar'}
]
df = [Link](data)
From numpy array
import numpy as np
arr = [Link]([[1, 2], [3, 4]])
df = [Link](arr, columns=['A', 'B'])
Q103: Pandas groupby()
groupby() performs SQL-like operations, grouping data by one or more columns:
import pandas as pd
df = [Link]({
'Type': ['Car', 'Bike', 'Car', 'Bike'],
'Brand': ['BMW', 'KTM', 'Audi', 'Pulsar'],
'Price': [50000, 150000, 60000, 100000]
})
Group by Type and count
[Link]('Type').count()
Group by Type and sum Price
[Link]('Type')['Price'].sum()
Group by Type and get mean Price
[Link]('Type')['Price'].mean()
Multiple grouping
[Link](['Type', 'Brand']).size()
Custom aggregation
[Link]('Type')['Price'].agg(['min', 'max', 'mean'])
Result: Mean price per Type
Type
Bike 125000
Car 55000
Q104: Create 5x5 NumPy zeros array
import numpy as np
Create 5x5 array of zeros
zeros_array = [Link]((5, 5))
Result:
[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
Variations
[Link]((3, 4)) # 3x4 array
[Link]((2, 2, 2)) # 2x2x2 3D array
[Link](10) # 1D array of 10 elements
Specify data type
[Link]((5, 5), dtype=int) # Integer zeros
[Link]((5, 5), dtype=bool) # Boolean zeros
Create ones array
[Link]((5, 5))
Create empty array (uninitialized)
[Link]((5, 5))
Create array with specific value
[Link]((5, 5), 7) # All elements are 7
Q105: DataFrame head() and tail()
import pandas as pd
df = [Link]({
'A': range(1, 11),
'B': range(10, 20)
})
Get first 5 rows (default)
[Link]()
Get first N rows
[Link](3) # First 3 rows
[Link](1) # First 1 row
Get last 5 rows (default)
[Link]()
Get last N rows
[Link](3) # Last 3 rows
[Link](1) # Last 1 row
Head and tail together
print([Link](3))
print([Link](3))
Useful for inspecting beginning and end of
large datasets
Q106: Drop rows with NaN values
import pandas as pd
import numpy as np
df = [Link]({
'A': [1, 2, [Link], 4],
'B': [5, [Link], 7, 8],
'C': [9, 10, 11, 12]
})
Remove rows with any NaN
[Link]()
Remove rows where all values are NaN
[Link](how='all')
Remove rows with NaN in specific column
[Link](subset=['A'])
Inplace modification
[Link](inplace=True)
Fill NaN instead of dropping
[Link](0) # Fill with 0
[Link](method='ffill') # Forward fill (use previous value)
[Link](method='bfill') # Backward fill (use next value)
Q107: Add column to DataFrame
import pandas as pd
df = [Link]({
'col1': [10, 20, 30],
'col2': [100, 200, 300]
})
Add new column with calculation
df['total'] = df['col1'] + df['col2']
Add column with constant value
df['status'] = 'active'
Add column with Series
df['col3'] = [Link]([1, 2, 3])
Using assign() (returns new DataFrame)
df_new = [Link](doubled=df['col1'] * 2)
Add column based on conditions
df['category'] = df['col1'].apply(
lambda x: 'High' if x > 15 else 'Low'
)
Result:
col1 col2 total
0 10 100 110
1 20 200 220
2 30 300 330
⭐⭐⭐ ADVANCED LEVEL
Object-Oriented Programming (Q121-145)
Q121: Classes and Objects
Classes are blueprints for creating objects, with attributes and methods:
Define a class
class Person:
# Class variable (shared by all instances)
species = "Homo sapiens"
# Constructor method
def __init__(self, name, age):
# Instance variables (unique to each object)
[Link] = name
[Link] = age
# Instance method
def greet(self):
return f"Hello, I'm {[Link]}"
# Another method
def have_birthday(self):
[Link] += 1
Create objects (instances)
person1 = Person("Alice", 30)
person2 = Person("Bob", 25)
Access attributes
print([Link]) # "Alice"
print([Link]) # "Homo sapiens"
Call methods
print([Link]()) # "Hello, I'm Alice"
person1.have_birthday()
print([Link]) # 31
Key concepts:
Class variables: Shared by all instances
Instance variables: Unique to each object
Methods: Functions that operate on instances
__init__: Constructor, called when creating new objects
⭐⭐⭐⭐ EXPERT+ LEVEL
Advanced Concepts
Decorators
Decorators are functions that modify other functions or classes without permanently
changing their source code:
Basic decorator
def my_decorator(func):
def wrapper():
print("Something before")
func()
print("Something after")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
Output:
Something before
Hello!
Something after
Decorator with arguments
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
Output: Hello, Alice! (printed 3 times)
Common use cases: Logging, authentication, caching, performance measurement.
Generators
Generators are functions that yield values one at a time instead of returning all values at
once:
Generator function (uses yield)
def count_up_to(n):
i=1
while i <= n:
yield i
i += 1
Use generator
gen = count_up_to(3)
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
Iterate through generator
for num in count_up_to(3):
print(num)
Generator expression (like list
comprehension)
gen = (x**2 for x in range(5))
list(gen) # [0, 1, 4, 9, 16]
Benefits: Memory efficient, lazy evaluation
Type Hints
Type hints provide information about expected data types (not enforced at runtime):
Function type hints
def add(x: int, y: int) -> int:
return x + y
Variable type hints
name: str = "Alice"
age: int = 30
numbers: list = [1, 2, 3]
Advanced type hints
from typing import List, Dict, Optional, Union
def process_data(items: List[int]) -> Dict[str, int]:
return {"sum": sum(items), "count": len(items)}
def find_user(user_id: int) -> Optional[str]:
# Returns string or None
return None
Union types
def handle_input(value: Union[int, str]) -> None:
pass
References
This comprehensive handbook covers Python interview questions across all difficulty levels
with detailed, practical explanations suitable for interview preparation.