Skip to main content

Python Interview Questions

Introduction

Python has become one of the most popular programming languages in the world, widely used in web development, data analysis, machine learning, and automation. As a result, Python programming skills are in high demand, and interviews for Python-related positions often include specific questions to test your knowledge of the language.

This guide covers common Python interview questions you might encounter, along with detailed explanations and examples to help you prepare. Whether you're a beginner looking for your first Python role or an experienced developer brushing up on fundamentals, these questions will help you demonstrate your Python expertise during interviews.

Basic Python Questions

1. What is Python?

Answer: Python is a high-level, interpreted programming language known for its readability and simplicity. It emphasizes code readability with its notable use of significant indentation, making it beginner-friendly while remaining powerful enough for professional use.

Key features include:

  • Interpreted language (not compiled)
  • Dynamically typed
  • Object-oriented
  • Supports multiple programming paradigms (procedural, functional)
  • Extensive standard library
  • Large and active community

2. What are the key features of Python?

Answer: Python has several distinctive features that make it popular:

  • Easy to Learn and Read: Simple syntax and emphasis on readability
  • Interpreted: Code is executed line by line
  • Dynamically Typed: Variable types are determined at runtime
  • Object-Oriented: Supports classes and objects
  • Extensive Libraries: Rich standard library and third-party packages
  • Platform Independent: Runs on various operating systems
  • Free and Open Source: Anyone can use, modify, and distribute
  • Integration Capability: Can be integrated with other languages like C, C++, Java
  • Extensible: Can add low-level modules to the Python interpreter
  • Memory Management: Automatic memory management

3. What's the difference between Python 2 and Python 3?

Answer: While Python 2 is now deprecated (support ended in 2020), this remains a common interview question:

FeaturePython 2Python 3
Print Statementprint "Hello"print("Hello")
Integer Division5/2 = 2 (returns integer)5/2 = 2.5 (returns float)
Unicode SupportASCII by defaultUTF-8 by default
Iteratorsrange(), xrange()range() only (works like xrange())
Exception Handlingexcept Exception, e:except Exception as e:
Input Functionraw_input()input()

4. What are Python data types?

Answer: Python has several built-in data types:

  • Numeric Types:

    • int: Integer values (e.g., 42)
    • float: Decimal values (e.g., 3.14)
    • complex: Complex numbers (e.g., 1+2j)
  • Sequence Types:

    • str: Strings (e.g., "hello")
    • list: Ordered, mutable collections (e.g., [1, 2, 3])
    • tuple: Ordered, immutable collections (e.g., (1, 2, 3))
  • Mapping Type:

    • dict: Key-value pairs (e.g., {"name": "John", "age": 30})
  • Set Types:

    • set: Unordered collection of unique elements (e.g., {1, 2, 3})
    • frozenset: Immutable version of set
  • Boolean Type:

    • bool: True or False
  • Binary Types:

    • bytes: Immutable sequence of bytes
    • bytearray: Mutable sequence of bytes
    • memoryview: Memory view of an object

5. How is memory managed in Python?

Answer: Python manages memory through a private heap space:

  • All Python objects and data structures are located in a private heap
  • The Python memory manager handles memory allocation
  • Built-in garbage collection recycles unused memory
  • Reference counting is the primary method for memory management
  • The gc module allows control over garbage collection for special cases
python
import gc

# Get current garbage collection thresholds
print(gc.get_threshold()) # Output: (700, 10, 10)

# Manually trigger garbage collection
gc.collect()

Data Structures and Advanced Concepts

6. What is the difference between a list and a tuple?

Answer:

Lists and tuples are both sequence data types, but they have key differences:

FeatureListTuple
Syntax[1, 2, 3](1, 2, 3)
MutabilityMutable (can be changed)Immutable (cannot be changed)
MethodsMore methods (append, extend, insert, remove, etc.)Fewer methods (count, index)
PerformanceSlightly slowerSlightly faster
Use CaseWhen you need to modify collectionWhen data shouldn't change
MemoryMore memoryLess memory

Example:

python
# List example
my_list = [1, 2, 3]
my_list[0] = 10 # Valid - lists are mutable
print(my_list) # Output: [10, 2, 3]

# Tuple example
my_tuple = (1, 2, 3)
# my_tuple[0] = 10 # Invalid - would raise TypeError
print(my_tuple) # Output: (1, 2, 3)

7. What is a dictionary in Python?

Answer: A dictionary is an unordered collection of key-value pairs. Keys must be unique and immutable (strings, numbers, tuples), while values can be of any type.

python
# Creating a dictionary
student = {
"name": "John",
"age": 21,
"courses": ["Math", "Physics", "Computer Science"]
}

# Accessing values
print(student["name"]) # Output: John

# Adding a new key-value pair
student["gpa"] = 3.8

# Updating a value
student["age"] = 22

# Dictionary methods
print(student.keys()) # Get all keys
print(student.values()) # Get all values
print(student.items()) # Get all key-value pairs

# Checking if a key exists
if "name" in student:
print("Name exists")

8. Explain list comprehensions in Python.

Answer: List comprehensions provide a concise way to create lists based on existing lists or other iterable objects. They follow the pattern:

[expression for item in iterable if condition]

Examples:

python
# Create a list of squares
squares = [x**2 for x in range(10)]
print(squares) # Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# List of even numbers
even_numbers = [x for x in range(20) if x % 2 == 0]
print(even_numbers) # Output: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# Convert Celsius to Fahrenheit
celsius = [0, 10, 20, 30, 40]
fahrenheit = [(9/5) * c + 32 for c in celsius]
print(fahrenheit) # Output: [32.0, 50.0, 68.0, 86.0, 104.0]

# Nested list comprehension (flattening a 2D list)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened) # Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]

9. What are Python generators?

Answer: Generators are functions that return an iterator that yields items one at a time. They use the yield statement instead of return and maintain their state between calls, allowing for memory-efficient iteration.

python
# Simple generator function
def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1

# Using the generator
counter = count_up_to(5)
print(next(counter)) # Output: 1
print(next(counter)) # Output: 2

# Using in a for loop
for number in count_up_to(5):
print(number) # Outputs: 1, 2, 3, 4, 5

# Generator expression (similar to list comprehension but uses parentheses)
squares = (x**2 for x in range(5))
print(list(squares)) # Output: [0, 1, 4, 9, 16]

Benefits of generators:

  • Memory efficient (don't store all values in memory)
  • Can work with infinite sequences
  • Lazy evaluation (compute values only when needed)

Object-Oriented Programming

10. Explain Python's object-oriented programming features.

Answer: Python is a fully object-oriented language with the following OOP features:

  1. Classes and Objects: Blueprint (class) and instance (object)
  2. Inheritance: Creating new classes based on existing ones
  3. Encapsulation: Restricting access to methods and variables
  4. Polymorphism: Same interface for different underlying forms
  5. Abstraction: Hiding complexity and showing only essentials

Example:

python
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species

def make_sound(self):
pass

def __str__(self):
return f"{self.name} is a {self.species}"

class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name, "Dog")
self.breed = breed

def make_sound(self):
return "Woof!"

class Cat(Animal):
def __init__(self, name, breed):
super().__init__(name, "Cat")
self.breed = breed

def make_sound(self):
return "Meow!"

# Creating objects
dog = Dog("Buddy", "Golden Retriever")
cat = Cat("Whiskers", "Siamese")

# Polymorphism demonstration
for animal in [dog, cat]:
print(animal)
print(f"Sound: {animal.make_sound()}")

11. What is inheritance in Python?

Answer: Inheritance allows a class to inherit attributes and methods from another class. The original class is called the parent or base class, and the derived class is called the child or subclass.

Types of inheritance in Python:

  • Single inheritance: A class inherits from one base class
  • Multiple inheritance: A class inherits from multiple base classes
  • Multilevel inheritance: A class inherits from a derived class
  • Hierarchical inheritance: Multiple classes inherit from one base class
python
# Base class
class Vehicle:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year

def start_engine(self):
return "Engine started!"

def get_info(self):
return f"{self.year} {self.make} {self.model}"

# Single inheritance
class Car(Vehicle):
def __init__(self, make, model, year, fuel_type):
super().__init__(make, model, year)
self.fuel_type = fuel_type
self.wheels = 4

def honk(self):
return "Beep beep!"

# Multiple inheritance
class Amphibious:
def __init__(self):
self.can_swim = True

def enter_water(self):
return "Entering water mode"

class AmphibiousCar(Car, Amphibious):
def __init__(self, make, model, year, fuel_type):
Car.__init__(self, make, model, year, fuel_type)
Amphibious.__init__(self)

# Testing
my_car = Car("Toyota", "Corolla", 2022, "Gasoline")
print(my_car.get_info()) # Output: 2022 Toyota Corolla
print(my_car.start_engine()) # Output: Engine started!

duck_car = AmphibiousCar("Duck", "Swimmer", 2023, "Hybrid")
print(duck_car.enter_water()) # Output: Entering water mode
print(duck_car.honk()) # Output: Beep beep!

12. What are Python decorators?

Answer: Decorators are a powerful way to modify or enhance functions or methods without changing their code. They are functions that take another function as an argument, add some functionality, and return a new function.

python
# Simple decorator
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper

@my_decorator
def say_hello():
print("Hello!")

# Calling the decorated function
say_hello()
# Output:
# Something is happening before the function is called.
# Hello!
# Something is happening after the function is called.

# Decorator with parameters
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator

@repeat(3)
def greet(name):
print(f"Hello {name}")

greet("Alice")
# Output:
# Hello Alice
# Hello Alice
# Hello Alice

Common use cases for decorators:

  • Logging
  • Timing functions
  • Authentication and authorization
  • Caching
  • Input validation

Advanced Python Concepts

13. Explain the Global Interpreter Lock (GIL) in Python.

Answer: The Global Interpreter Lock (GIL) is a mutex (or lock) that protects access to Python objects, preventing multiple threads from executing Python bytecode at once. This means that in CPython (the standard Python implementation), only one thread can execute Python code at any given time, even on multi-core processors.

Key points about the GIL:

  • It makes multi-threaded CPU-bound programs slower than single-threaded ones
  • It doesn't affect I/O-bound multi-threaded programs much
  • It simplifies memory management and makes the CPython implementation easier
  • It doesn't affect multi-process applications (using the multiprocessing module)

Ways to work around the GIL:

  • Use the multiprocessing module instead of threads for CPU-bound tasks
  • Use C extensions that release the GIL
  • Use alternative Python implementations like Jython or IronPython (which don't have a GIL)

14. What are Python context managers?

Answer: Context managers in Python handle the setup and teardown of resources. The most common way to use them is with the with statement, which ensures resources are properly managed even if exceptions occur.

python
# Using a context manager for file operations
with open('example.txt', 'w') as file:
file.write('Hello, World!')
# File is automatically closed when exiting the with block

# Creating a custom context manager using a class
class MyContextManager:
def __init__(self, name):
self.name = name

def __enter__(self):
print(f"Entering context with {self.name}")
return self # Return value assigned to variable in with statement

def __exit__(self, exc_type, exc_val, exc_tb):
print(f"Exiting context with {self.name}")
# Return True to suppress exceptions, False to propagate them
if exc_type is not None:
print(f"An exception occurred: {exc_val}")
return False

# Using the custom context manager
with MyContextManager("test") as cm:
print("Inside the context")
# raise ValueError("Something went wrong")

# Creating a context manager using contextlib
from contextlib import contextmanager

@contextmanager
def my_context(name):
print(f"Entering context with {name}")
try:
yield name # This value is assigned to the variable in the with statement
finally:
print(f"Exiting context with {name}")

with my_context("test") as name:
print(f"Inside context with {name}")

15. What are Python's magic methods (dunder methods)?

Answer: Magic methods (also called dunder methods for "double underscore") are special methods with double underscores at the beginning and end. They allow you to define how objects of your class behave with built-in functions and operators.

Common magic methods:

python
class CustomNumber:
def __init__(self, value):
self.value = value

# String representation
def __str__(self):
return f"CustomNumber({self.value})"

def __repr__(self):
return f"CustomNumber({self.value})"

# Arithmetic operations
def __add__(self, other):
if isinstance(other, CustomNumber):
return CustomNumber(self.value + other.value)
return CustomNumber(self.value + other)

def __sub__(self, other):
if isinstance(other, CustomNumber):
return CustomNumber(self.value - other.value)
return CustomNumber(self.value - other)

# Comparison operations
def __eq__(self, other):
if isinstance(other, CustomNumber):
return self.value == other.value
return self.value == other

def __lt__(self, other):
if isinstance(other, CustomNumber):
return self.value < other.value
return self.value < other

# Container methods
def __len__(self):
return len(str(self.value))

# Context manager protocol
def __enter__(self):
print(f"Entering context with {self.value}")
return self

def __exit__(self, exc_type, exc_val, exc_tb):
print(f"Exiting context with {self.value}")
return False

# Using our custom class
num1 = CustomNumber(5)
num2 = CustomNumber(10)

# Addition works because of __add__
print(num1 + num2) # Output: CustomNumber(15)

# Comparison works because of __eq__ and __lt__
print(num1 == 5) # Output: True
print(num1 < num2) # Output: True

# Length works because of __len__
print(len(num1)) # Output: 1 (length of "5")

# Context manager works because of __enter__ and __exit__
with CustomNumber(42) as num:
print(f"Working with {num}")

Practical Python Questions

16. How would you remove duplicates from a list while preserving order?

Answer: There are several ways to remove duplicates from a list while preserving the original order:

python
# Option 1: Using a list comprehension with a set for tracking
def remove_duplicates_v1(items):
seen = set()
return [item for item in items if not (item in seen or seen.add(item))]

# Option 2: Using dict.fromkeys() (since Python 3.7 dicts preserve insertion order)
def remove_duplicates_v2(items):
return list(dict.fromkeys(items))

# Option 3: Using a generator function
def remove_duplicates_v3(items):
seen = set()
for item in items:
if item not in seen:
seen.add(item)
yield item

# Testing with a sample list
original = [1, 2, 3, 1, 2, 5, 6, 7, 8, 1, 3, 4]

print(remove_duplicates_v1(original)) # [1, 2, 3, 5, 6, 7, 8, 4]
print(remove_duplicates_v2(original)) # [1, 2, 3, 5, 6, 7, 8, 4]
print(list(remove_duplicates_v3(original))) # [1, 2, 3, 5, 6, 7, 8, 4]

17. Write a function to check if a string is a palindrome.

Answer: A palindrome is a string that reads the same backward as forward (ignoring spaces, punctuation, and capitalization).

python
def is_palindrome(s):
# Convert to lowercase and remove non-alphanumeric characters
s = ''.join(char.lower() for char in s if char.isalnum())

# Check if the string equals its reverse
return s == s[::-1]

# Test cases
test_strings = [
"racecar",
"A man, a plan, a canal: Panama",
"Was it a car or a cat I saw?",
"No 'x' in Nixon",
"Not a palindrome"
]

for string in test_strings:
print(f"'{string}': {is_palindrome(string)}")

# Output:
# 'racecar': True
# 'A man, a plan, a canal: Panama': True
# 'Was it a car or a cat I saw?': True
# 'No 'x' in Nixon': True
# 'Not a palindrome': False

18. Implement a function to find the first non-repeated character in a string.

Answer: This problem tests dictionary usage and string manipulation:

python
def first_non_repeated_char(s):
# Count occurrences of each character
char_count = {}
for char in s:
char_count[char] = char_count.get(char, 0) + 1

# Find the first character with count 1
for char in s:
if char_count[char] == 1:
return char

# No non-repeated character found
return None

# Test cases
test_strings = [
"programming", # First non-repeated character: 'p'
"aabbc", # First non-repeated character: 'c'
"aabbcc", # No non-repeated character
"z" # First non-repeated character: 'z'
]

for string in test_strings:
result = first_non_repeated_char(string)
if result:
print(f"First non-repeated character in '{string}': '{result}'")
else:
print(f"No non-repeated character in '{string}'")

# Output:
# First non-repeated character in 'programming': 'p'
# First non-repeated character in 'aabbc': 'c'
# No non-repeated character in 'aabbcc'
# First non-repeated character in 'z': 'z'

19. Create a simple function for FizzBuzz.

Answer: FizzBuzz is a classic programming problem that tests conditional logic:

python
def fizzbuzz(n):
"""
For numbers 1 to n:
- Print "Fizz" if divisible by 3
- Print "Buzz" if divisible by 5
- Print "FizzBuzz" if divisible by both 3 and 5
- Print the number if none of the above
"""
result = []
for i in range(1, n+1):
if i % 3 == 0 and i % 5 == 0:
result.append("FizzBuzz")
elif i % 3 == 0:
result.append("Fizz")
elif i % 5 == 0:
result.append("Buzz")
else:
result.append(str(i))
return result

# Test with n = 20
for item in fizzbuzz(20):
print(item)

# One-liner solution using list comprehension
def fizzbuzz_oneliner(n):
return ["FizzBuzz" if i % 15 == 0 else "Fizz" if i % 3 == 0 else "Buzz" if i % 5 == 0 else str(i) for i in range(1, n+1)]

Output for fizzbuzz(20):

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz

Python Libraries and Ecosystem

Answer: Python has a rich ecosystem of libraries for various purposes:

Data Science and Machine Learning:

  • NumPy: Numerical computing with multi-dimensional arrays
  • Pandas: Data manipulation and analysis
  • Matplotlib/Seaborn: Data visualization
  • Scikit-learn: Machine learning algorithms
  • TensorFlow/PyTorch: Deep learning frameworks

Web Development:

  • Django: Full-featured web framework
  • Flask: Lightweight web framework
  • FastAPI: Modern API framework
  • Requests: HTTP library

Automation and Scripting:

  • Beautiful Soup: Web scraping
  • Selenium: Browser automation
  • Paramiko: SSH client
  • PyAutoGUI: GUI automation

Desktop Applications:

  • Tkinter: Standard GUI library
  • PyQt/PySide: Qt-based GUI frameworks
  • Kivy: Multi-touch application framework

Testing:

  • pytest: Testing framework
  • unittest: Standard library testing
  • mock: Mocking objects for testing

Other Useful Libraries:

  • asyncio: Asynchronous I/O
  • collections: Specialized container types
  • itertools: Iterator building blocks
  • datetime: Date and time handling

21. Explain Python's virtual environments and why they're important.

Answer: A virtual environment is an isolated Python environment that allows you to install packages for a specific project without affecting the system-wide Python installation.

Benefits of virtual environments:

  • Dependency Isolation: Each project can have its own dependencies
  • Version Control: Different projects can use different versions of the same package
  • Clean Testing Environment: Test in a clean environment without unexpected dependencies
  • Easy Reproduction: Makes it easy to reproduce the environment on another machine

Creating and using virtual environments:

bash
# Using venv (built into Python 3)
python -m venv myenv

# Activating the environment
# On Windows:
myenv\Scripts\activate
# On Unix or MacOS:
source myenv/bin/activate

# Installing packages
pip install package_name

# Generating requirements.txt
pip freeze > requirements.txt

# Installing from requirements.txt
pip install -r requirements.txt

# Deactivating the environment
deactivate

Alternative tools:

  • virtualenv: The original virtual environment tool
  • pipenv: Combines pip and virtualenv
  • conda: Package and environment manager (popular in data science)
  • poetry: Dependency management and packaging

Common Coding Questions

22. Write a function to check if two strings are anagrams.

Answer: Anagrams are words or phrases formed by rearranging the letters of another word or phrase, using all the original letters exactly once.

python
def are_anagrams(s1, s2):
# Remove spaces and convert to lowercase
s1 = s1.replace(" ", "").lower()
s2 = s2.replace(" ", "").lower()

# Check if the sorted strings are equal
return sorted(s1) == sorted(s2)

# Alternative implementation using character counting
def are_anagrams_counter(s1, s2):
# Remove spaces and convert to lowercase
s1 = s1.replace(" ", "").lower()
s2 = s2.replace(" ", "").lower()

# If lengths are different, they can't be anagrams
if len(s1) != len(s2):
return False

# Count characters in both strings
char_count = {}

# Count characters in first string
for char in s1:
char_count[char] = char_count.get(char, 0) + 1

# Decrement counts for second string
for char in s2:
if char not in char_count:
return False
char_count[char] -= 1
if char_count[char] < 0:
return False

# All counts should be zero
return all(count == 0 for count in char_count.values())

# Test cases
test_cases = [
("listen", "silent"),
("rail safety", "fairy tales"),
("restful", "fluster"),
("funeral", "real fun"),
("adultery", "true lady"),
("customer", "store cut"),
("conversation", "voices rant on"),
("eleven plus two", "twelve plus one"),
("Fourth of July", "joyful Fourth")
]

for s1, s2 in test_cases:
print(f"'{s1}' and '{s2}' are anagrams: {are_anagrams(s1, s2)}")

23. How would you reverse a linked list in Python?

Answer: While Python doesn't have a built-in linked list data structure, we can implement one and reverse it:

python
class Node:
def __init__(self, data):
self.data = data
self.next = None

class LinkedList:
def __init__(self):
self.head = None

def append(self, data):
new_node = Node(data)
if not self.head:
self.head = new_node
return

current = self.head
while current.next:
current = current.next
current.next = new_node

def print_list(self):
current = self.head
elements = []
while current:
elements.append(str(current.data))
current = current.next
return " -> ".join(elements)

def reverse(self):
previous = None
current = self.head

while current:
# Store next node
next_node = current.next

# Reverse the link
current.next = previous

# Move pointers one position ahead
previous = current
current = next_node

# Update head
self.head = previous

# Create and test a linked list
llist = LinkedList()
elements = [1, 2, 3, 4, 5]
for element in elements:
llist.append(element)

print("Original list:", llist.print_list()) # 1 -> 2 -> 3 -> 4 -> 5
llist.reverse()
print("Reversed list:", llist.print_list()) # 5 -> 4 -> 3 -> 2 -> 1

24. Solve the "Two Sum" problem in Python.

Answer: The Two Sum problem asks: Given an array of integers and a target sum, return the indices of two numbers that add up to the target.

python
def two_sum(nums, target):
"""
Given an array of integers (nums) and a target integer (target),
return the indices of two numbers that add up to target.

Assumes there is exactly one solution and the same element can't be used twice.
"""
# Brute force approach - O(n²) time complexity
def brute_force():
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
if nums[i] + nums[j] == target:
return [i, j]
return None

# Optimized approach using hash map - O(n) time complexity
def optimized():
# Map of value -> index
num_map = {}

for i, num in enumerate(nums):
complement = target - num

# If complement exists in map, we found the solution
if complement in num_map:
return [num_map[complement], i]

# Add current number to


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)