Back to Blog
April 25, 2024
Pratyusha
en

Top 55 Python Interview Questions and Answers

Data Science
Python
Top 55 Python Interview Questions and Answers

Rising demand for python in end-end applications is due to,

  1. Increase in adoption of data analytics by enterprises

  2. Growing dependency on Python over other programming languages

  3. Increase in demand of python for real time Internet of Things 

{% module_block module "widget_cbd7e041-6719-4ddc-ba0d-56c5a115cc80" %}{% module_attribute "child_css" is_json="true" %}{% raw %}{}{% endraw %}{% end_module_attribute %}{% module_attribute "css" is_json="true" %}{% raw %}{}{% endraw %}{% end_module_attribute %}{% module_attribute "definition_id" is_json="true" %}{% raw %}null{% endraw %}{% end_module_attribute %}{% module_attribute "field_types" is_json="true" %}{% raw %}{"link":"text","text":"text"}{% endraw %}{% end_module_attribute %}{% module_attribute "label" is_json="true" %}{% raw %}null{% endraw %}{% end_module_attribute %}{% module_attribute "link" is_json="true" %}{% raw %}"https://www.odinschool.com/blog/python-jobs-2024"{% endraw %}{% end_module_attribute %}{% module_attribute "module_id" is_json="true" %}{% raw %}135590387735{% endraw %}{% end_module_attribute %}{% module_attribute "path" is_json="true" %}{% raw %}"/OdinSchool_V3/modules/Blog/blog - source links"{% endraw %}{% end_module_attribute %}{% module_attribute "schema_version" is_json="true" %}{% raw %}2{% endraw %}{% end_module_attribute %}{% module_attribute "smart_objects" is_json="true" %}{% raw %}null{% endraw %}{% end_module_attribute %}{% module_attribute "smart_type" is_json="true" %}{% raw %}"NOT_SMART"{% endraw %}{% end_module_attribute %}{% module_attribute "tag" is_json="true" %}{% raw %}"module"{% endraw %}{% end_module_attribute %}{% module_attribute "text" is_json="true" %}{% raw %}"Look at different Python Jobs in 2024"{% endraw %}{% end_module_attribute %}{% module_attribute "type" is_json="true" %}{% raw %}"module"{% endraw %}{% end_module_attribute %}{% module_attribute "wrap_field_tag" is_json="true" %}{% raw %}"div"{% endraw %}{% end_module_attribute %}{% end_module_block %}

 

Python Interview Questions - Infographic

Python Interview Questions

Following are the topics on which Python interviews are conducted, so here are some Python interview questions with answers that might help you know how prepared you are.

Python Fundamentals

Questions may include topics like data types, variables, basic operators, and understanding Python's syntax and semantics.

Q1: Demonstrate the difference between a shallow copy and a deep copy when working with a list of lists in Python. Provide code examples that illustrate potential issues with each method.

# Create a list containing other lists
original = [[1, 2, 3], [4, 5, 6]]

# Shallow copy
shallow_copied = copy.copy(original)
shallow_copied[0][0] = 0

# Deep copy
deep_copied = copy.deepcopy(original)
deep_copied[1][1] = 0

print("Original:", original)  # Original: [[0, 2, 3], [4, 5, 6]], showing that shallow copy affected the original
print("Shallow Copied:", shallow_copied)  # Shallow Copied: [[0, 2, 3], [4, 5, 6]]
print("Deep Copied:", deep_copied)  # Deep Copied: [[1, 2, 3], [4, 0, 6]]

This example demonstrates how changes to a list within the list affect the original list when a shallow copy is used, due to both sharing references to the same inner lists. A deep copy, on the other hand, creates new inner lists, so changes do not affect the original.

Q2: How can cyclic dependencies in imports be problematic in Python? Provide an example and explain a strategy to resolve such issues.

Cyclic dependencies occur when two more modules depend on each other either directly or indirectly, causing an infinite loop and potential ImportError. Here's a simplified example:

module_a.py:

from module_b import B
class A:
    def __init__(self):
        self.b = B()

module_b.py:
from module_a import A
class B:
    def __init__(self):
        self.a = A()

This structure will lead to an ImportError. A solution is to refactor the import statements:
# In module_b.py
class B:
    def __init__(self):
        from module_a import A
        self.a = A()

By moving the import statement inside the method or function, it defers the loading of the dependent module until it's needed, breaking the cyclic dependency.

Q3: Write a Python context manager that logs entry and exit from a block of code, demonstrating resource management.

from contextlib import contextmanager
import time

@contextmanager
def timed_block(label):
    start_time = time.time()
    try:
        yield
    finally:
        end_time = time.time()
        print(f"{label} took {end_time - start_time:.3f} seconds")

# Usage:
with timed_block("Processing"):
    sum = 0
    for i in range(1000000):
        sum += i

Q4: Implement a memoization decorator that caches the results of a function based on its arguments.

def memoize(f):
    memo = {}
    def helper(x):
        if x not in memo:            
            memo[x] = f(x)
        return memo[x]
    return helper

@memoize
def fib(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fib(n-1) + fib(n-2)
Q5: Explain a common pitfall in Python's asyncio library and how to avoid it. Provide a code example.

One common pitfall is calling an asynchronous function without await, which means the function is never actually executed. This often happens due to a misunderstanding of how coroutines work in Python.

import asyncio

async def do_work():
    print("Work Started")
    await asyncio.sleep(1)  # Simulate I/O task
    print("Work Finished")

async def main():
    # Incorrect call, does nothing
    do_work()  

    # Correct call
    await do_work()

asyncio.run(main())

Data Structures

Understanding and using Python's built-in data structures like lists, dictionaries, sets, and tuples. Questions might involve operations on these data structures, such as adding or removing elements, iterating, or sorting.

Q6: Implement a function to reverse a singly linked list in Python without using any additional data structures. Describe the algorithm and provide the code.

A: To reverse a singly linked list, you need to change the next pointers of each node so that they point to the previous node. This can be achieved using three pointers: previous, current, and next.

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

def reverse_linked_list(head):
    previous = None
    current = head
    while current:
        next = current.next
        current.next = previous
        previous = current
        current = next
    return previous

# Example Usage
head = Node(1)
head.next = Node(2)
head.next.next = Node(3)
reversed_list = reverse_linked_list(head)
current = reversed_list
while current:
    print(current.data, end=" -> ")
    current = current.next

Q7: Using two stacks, implement a queue that supports all queue operations (enqueue, dequeue) in amortized O(1) time. Explain the mechanism behind your solution and provide the implementation in Python.

The key idea is to use two stacks, stack_in for enqueue operations and stack_out for dequeue operations. When stack_out is empty and a dequeue is required, the contents of stack_in are transferred to stack_out, reversing the order and making the oldest element available.

class QueueWithStacks:
    def __init__(self):
        self.stack_in = []
        self.stack_out = []

    def enqueue(self, x):
        self.stack_in.append(x)

    def dequeue(self):
        if not self.stack_out:
            while self.stack_in:
                self.stack_out.append(self.stack_in.pop())
        return self.stack_out.pop()

# Example Usage
q = QueueWithStacks()
q.enqueue(1)
q.enqueue(2)
q.enqueue(3)
print(q.dequeue())  # Output: 1
print(q.dequeue())  # Output: 2

Q8: Write a function to check whether a binary tree is a binary search tree (BST).

A BST is a tree in which each node contains a key greater than all the keys in the node's left subtree and less than those in its right subtree. To check this, perform an in-order traversal and ensure the resulting list of keys is sorted in ascending order.

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

def is_bst(node, lower=float('-inf'), upper=float('inf')):
    if not node:
        return True
    val = node.val
    if val <= lower or val >= upper:
        return False
    if not is_bst(node.right, val, upper):
        return False
    if not is_bst(node.left, lower, val):
        return False
    return True

# Example Usage
root = TreeNode(2)
root.left = TreeNode(1)
root.right = TreeNode(3)
print(is_bst(root))  # Output: True

Q9: Write a function to detect a cycle in a linked list. If a cycle exists, return the starting node of the cycle.

Floyd's Cycle Detection Algorithm (also known as the Tortoise and the Hare algorithm) is an efficient method to detect cycles. It uses two pointers moving at different speeds. If there is a cycle, the fast pointer (hare) will eventually meet the slow pointer (tortoise).

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

def detectCycle(head):
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            while head != slow:
                head = head.next
                slow = slow.next
            return head
    return None

# Example Usage
node1 = ListNode(3)
node2 = ListNode(2)
node3 = ListNode(0)
node4 = ListNode(-4)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node2  # Creates a cycle that starts at node2

print(detectCycle(node1).val)  # Output: 2

Q10: Implement an LRU (Least Recently Used) cache that supports the get and put operations.

An LRU cache can be implemented using a combination of a doubly linked list and a hash map. The doubly linked list maintains items in order of usage, with the least recently used items near the tail and the most recently used near the head. The hash map stores keys and pointers to the corresponding nodes in the doubly linked list to ensure O(1) access time.

class LRUCache:
    class Node:
        def __init__(self, key, value):
            self.key = key
            self.value = value
            self.prev = None
            self.next = None

    def __init__(self, capacity):
        self.capacity = capacity
        self.dict = {}
        self.head = self.Node(0, 0)
        self.tail = self.Node(0, 0)
        self.head.next = self.tail
        self.tail.prev = self.head

    def get(self, key):
        if key in self.dict:
            n = self.dict[key]
            self._remove(n)
            self._add(n)
            return n.value
        return -1

    def put(self, key, value):
        if key in self.dict:
            self._remove(self.dict[key])
        n = self.Node(key, value)
        self._add(n)
        self.dict[key] = n
        if len(self.dict) > self.capacity:
            n = self.head.next
            self._remove(n)
            del self.dict[n.key]

    def _remove(self, node):
        p, n = node.prev, node.next
        p.next, n.prev = n, p

    def _add(self, node):
        p = self.tail.prev
        p.next = node
        self.tail.prev = node
        node.prev = p
        node.next = self.tail

# Example Usage
cache = LRUCache(2)
cache.put(1, 1)
cache.put(2, 2)
print(cache.get(1))       # returns 1
cache.put(3, 3)           # evicts key 2
print(cache.get(2))       # returns -1 (not found)

Control Structures

Knowledge of conditional statements (if, elif, else), loops (for, while), and comprehension techniques is mandatory.

Q11: Write a function to find the position of a given value in a sorted 2D matrix where each row and each column is sorted in ascending order. Assume no duplicates. Provide both the position and the Python code.

This problem can be approached by using a staircase search algorithm, starting from the top-right corner and moving based on comparisons.

def search_in_sorted_matrix(matrix, target):
    if not matrix or not matrix[0]:
        return (-1, -1)
    row, col = 0, len(matrix[0]) - 1
    while row < len(matrix) and col >= 0:
        if matrix[row][col] == target:
            return (row, col)
        elif matrix[row][col] > target:
            col -= 1
        else:
            row += 1
    return (-1, -1)

# Example matrix and target
matrix = [
    [1, 4, 7, 11],
    [2, 5, 8, 12],
    [3, 6, 9, 16]
]
target = 8
print(search_in_sorted_matrix(matrix, target))  # Output: (1, 2)

Q12: Create a Python function that finds all unique triplets in an array that sum up to zero. Provide a solution that avoids using excessive brute force.

This can be solved efficiently using a combination of sorting and the two-pointer technique.

def three_sum(nums):
    nums.sort()
    result = []
    for i in range(len(nums) - 2):
        if i > 0 and nums[i] == nums[i - 1]:
            continue
        left, right = i + 1, len(nums) - 1
        while left < right:
            total = nums[i] + nums[left] + nums[right]
            if total < 0:
                left += 1
            elif total > 0:
                right -= 1
            else:
                result.append([nums[i], nums[left], nums[right]])
                while left < right and nums[left] == nums[left + 1]:
                    left += 1
                while left < right and nums[right] == nums[right - 1]:
                    right -= 1
                left += 1
                right -= 1
    return result

# Example usage
nums = [-1, 0, 1, 2, -1, -4]
print(three_sum(nums))  # Output: [[-1, -1, 2], [-1, 0, 1]]

Q13: Implement a Python function that returns the first recurring character in a string using a single pass and without additional data structures.

This can be challenging due to the constraints, but can be approached by using bitwise operations to check seen characters, assuming the string only contains letters a-z.

def first_recurring_character(s):
    seen = 0
    for char in s:

Related Articles