InterviewQAs

Python Dictionaries

Download as PDF
All questions in this page are included
Preparing…
Download PDF
PD
Python Dictionaries

Python dictionaries are a versatile data structure widely used in backend systems, ETL pipelines, and API transformations for fast key-value access and dynamic data modeling.

They support complex nesting, efficient lookups, and mutable values, making them ideal for caching, grouping, and analytics processing in production environments.

Intermediate and advanced interviews often explore dictionary edge cases, mutation safety, deep vs shallow copying, and performance considerations for large datasets.

Experienced engineers leverage dictionaries to implement aggregation logic, configuration management, event processing, and caching mechanisms efficiently.

Understanding Python dictionaries ensures developers can build reliable, high-performance, and maintainable solutions in real-world applications while avoiding subtle bugs.

Question 01

How do you safely update a nested dictionary without overwriting existing subkeys?

MEDIUM

Updating nested dictionaries directly may overwrite entire subkeys unintentionally. To avoid this, recursive update or merge logic should be used, which updates only the keys provided while preserving other subkeys.

For example, in configuration management, a partial update should modify only the overridden fields without removing existing settings.

Python's copy.deepcopy() combined with recursive merging ensures updates do not affect the original dictionary while maintaining existing structure and values.

Question 02

Which dictionary methods can be used to handle missing keys gracefully?

MEDIUM
  • A get()
  • B pop() with default
  • C setdefault()
  • D del

get() returns a default value instead of raising KeyError.

pop() allows specifying a default to avoid KeyError when removing keys.

setdefault() initializes the key if it does not exist.

Question 03

Write a Python function to merge two dictionaries, summing numeric values for duplicate keys.

HARD

This approach handles numeric accumulation while safely adding new keys.

It is useful in scenarios like transaction aggregation, inventory adjustments, or analytics where multiple data sources contribute numeric values.

# Python
def merge_sum_dicts(d1, d2):
    result = d1.copy()
    for key, value in d2.items():
        if key in result and isinstance(result[key], (int, float)) and isinstance(value, (int, float)):
            result[key] += value
        else:
            result[key] = value
    return result

print(merge_sum_dicts({'a': 10, 'b': 5}, {'a': 3, 'c': 7}))
Question 04

Explain how dictionary keys are hashed and why hashability is important.

MEDIUM

Python dictionaries use hash tables where keys are hashed to determine storage location. Only hashable objects (immutable and with __hash__ defined) can be used as keys.

Hashability ensures that a key's hash remains constant during its lifetime, providing O(1) average lookup and insertion performance.

Understanding hashability is crucial for using tuples, frozensets, or custom objects as dictionary keys in real-world applications.

Question 05

Which practices can improve dictionary performance with very large datasets?

HARD
  • A Use immutable keys
  • B Pre-size dictionaries
  • C Avoid hash collisions
  • D Use nested lists instead of dictionaries

Immutable keys provide consistent hash values.

Pre-sizing dictionaries can reduce rehashing overhead for large datasets.

Avoiding hash collisions ensures lookups remain efficient. Nested lists increase lookup time and are not efficient for key-based access.

Question 06

Write a Python snippet to count occurrences of items in a list using dictionaries.

MEDIUM

Dictionaries efficiently track counts with O(1) key lookups.

This pattern is common in log aggregation, event counting, and frequency analysis.

# Python
items = ['apple', 'banana', 'apple', 'orange', 'banana']
counts = {}
for item in items:
    counts[item] = counts.get(item, 0) + 1
print(counts)
Question 07

Describe how dictionary views like keys(), values(), and items() reflect changes dynamically.

MEDIUM

Dictionary views provide live views of the dictionary's keys, values, or key-value pairs.

Any modification to the dictionary (adding, updating, or deleting keys) is immediately reflected in the views without creating a copy.

This behavior is useful for real-time monitoring, filtering, or iteration over changing data structures in production applications.

Question 08

Which statements about dictionary insertion order are correct?

EASY
  • A Dictionaries maintain insertion order since Python 3.7
  • B The first key inserted is always the first key returned in iteration
  • C Dictionaries automatically sort keys alphabetically
  • D OrderedDict is still needed for pre-3.7 Python

Python 3.7+ guarantees insertion order for dictionaries.

Prior to 3.7, OrderedDict was needed for deterministic order.

Dictionaries do not automatically sort keys; iteration follows insertion order only.

Question 09

Write a Python function that recursively finds all keys matching a certain pattern in nested dictionaries.

HARD

Recursively scanning nested dictionaries allows searching arbitrary depth for keys matching a regex pattern.

This is useful in configuration auditing, API payload validation, and extracting metadata from dynamic nested JSON structures.

# Python
import re

def find_keys_pattern(d, pattern):
    matches = []
    for k, v in d.items():
        if re.search(pattern, k):
            matches.append(k)
        if isinstance(v, dict):
            matches.extend(find_keys_pattern(v, pattern))
    return matches

nested = {'user_name': 'Vijay', 'profile': {'user_email': 'v@test.com', 'details': {}}}
print(find_keys_pattern(nested, r'user_.*'))
Question 10

Implement a dictionary-based configuration cache with default values.

MEDIUM

Using get() with a default dictionary ensures safe access to configuration values even if the cache is missing keys.

This pattern is common in backend systems to separate defaults from runtime overrides and maintain predictable application behavior.

# Python
config_defaults = {'host': 'localhost', 'port': 8080, 'debug': False}
config_cache = {}

def get_config(key):
    return config_cache.get(key, config_defaults.get(key))

config_cache['port'] = 9090
print(get_config('port'))
print(get_config('debug'))
Question 11

Explain how using defaultdict can simplify dictionary-based aggregations.

MEDIUM

defaultdict automatically initializes a default value for missing keys, which eliminates the need for explicit key existence checks during aggregation.

For example, counting occurrences in a stream of events becomes simpler and cleaner using defaultdict(int), where missing keys start at zero.

This pattern is widely used in analytics pipelines, log aggregation, and frequency counts for backend services.

Question 12

Which of the following are valid ways to merge dictionaries in Python 3.8+?

EASY
  • A Using update() method
  • B Using the | operator (Python 3.9+)
  • C Using list comprehension
  • D Using a for loop to add keys manually

update() modifies the dictionary in place, merging another dictionary's key-values.

A for loop can manually add key-value pairs with custom conflict resolution logic. The | operator is only valid from Python 3.9+.

List comprehension cannot merge dictionaries directly.

Question 13

Write a Python function that recursively counts all keys in a nested dictionary.

HARD

Recursive traversal is used to count keys at all levels of a nested dictionary.

This is helpful in configuration management, nested JSON processing, and verifying schema completeness.

# Python
def count_nested_keys(d):
    count = 0
    for key, value in d.items():
        count += 1
        if isinstance(value, dict):
            count += count_nested_keys(value)
    return count

nested = {'a': 1, 'b': {'c': 2, 'd': {'e': 3}}}
print(count_nested_keys(nested))
Question 14

Describe potential pitfalls of using mutable objects as dictionary values.

MEDIUM

Mutable values like lists or dictionaries are stored by reference, so multiple references may point to the same object.

Unintended modifications to one reference can affect all references, causing side effects and subtle bugs.

To avoid this, developers use copy.deepcopy() or create new instances when updating mutable values, especially in nested dictionaries or shared data structures.

Question 15

Which of the following can cause issues when iterating over a dictionary?

HARD
  • A Adding new keys during iteration
  • B Deleting keys during iteration
  • C Modifying values of existing keys
  • D Iterating over a copy of keys

Adding or deleting keys during iteration can raise RuntimeError because the iterator's state is invalidated.

Modifying values of existing keys is safe since the dictionary structure remains unchanged.

Iterating over a list copy of keys avoids modification issues.

Question 16

Implement a Python dictionary that acts as a simple in-memory cache with TTL (time-to-live).

MEDIUM

Each cache entry stores the value and an expiration timestamp. Access checks current time against expiry.

This is useful for backend systems caching database queries, API responses, or session data.

# Python
import time

cache = {}

def set_cache(key, value, ttl_seconds):
    cache[key] = (value, time.time() + ttl_seconds)

def get_cache(key):
    value, expire = cache.get(key, (None, 0))
    if time.time() < expire:
        return value
    cache.pop(key, None)
    return None

set_cache('user1', {'role': 'ADMIN'}, 5)
print(get_cache('user1'))
Question 17

Why is it important to understand dictionary hash collisions in large datasets?

MEDIUM

Hash collisions occur when two different keys produce the same hash value, which can reduce lookup performance.

In large dictionaries, collisions may increase probing overhead and memory accesses.

Understanding collisions helps in designing hashable keys, reducing collisions, and ensuring predictable performance in high-volume systems.

Question 18

Which statements about dictionary copying are correct?

MEDIUM
  • A dict.copy() creates a shallow copy
  • B copy.deepcopy() creates an independent deep copy
  • C dict.copy() copies nested mutable objects
  • D Shallow copies share references of mutable nested objects

Shallow copy duplicates only the top-level dictionary. Nested mutable objects remain shared.

Deep copy duplicates all levels, creating completely independent objects.

Understanding this distinction is crucial when modifying nested dictionaries without affecting original data.

Question 19

Write a Python function that filters a dictionary based on a value condition.

HARD

Dictionary comprehension efficiently filters key-value pairs based on a condition.

This technique is commonly used in analytics, reporting, and preprocessing of API payloads.

# Python
def filter_dict(d, threshold):
    return {k: v for k, v in d.items() if v >= threshold}

scores = {'Alice': 85, 'Bob': 72, 'Charlie': 90}
print(filter_dict(scores, 80))
Question 20

Implement a Python dictionary-based frequency map for words in a string.

MEDIUM

This pattern counts occurrences of words efficiently using dictionary get() with a default value.

Word frequency counting is essential in text analytics, search indexing, and telemetry data aggregation.

# Python
text = 'python python dictionary cache python keys'
frequency = {}
for word in text.split():
    frequency[word] = frequency.get(word, 0) + 1
print(frequency)
Question 21

Explain why iterating over dictionary keys while modifying the dictionary can be risky and how to avoid it.

MEDIUM

Modifying a dictionary (adding or deleting keys) while iterating over it can raise RuntimeError because the iterator becomes invalid.

To avoid this, iterate over a snapshot list of keys using list(dict.keys()) or use dictionary comprehension to create a modified copy.

This ensures safe iteration and avoids subtle runtime errors in production code, especially in event processing or configuration updates.

Question 22

Which of the following are valid ways to create a dictionary in Python?

MEDIUM
  • A Using curly braces {} with key-value pairs
  • B Using dict() with keyword arguments
  • C Using dict() with a list of tuples
  • D Using list() with key-value pairs

Curly braces are the most common syntax. dict() can also be initialized using keyword arguments or iterable of tuples. list() cannot create dictionaries directly.

Question 23

Write a Python function that merges multiple dictionaries and sums integer values for duplicate keys.

HARD

This approach handles aggregation of numeric values while adding new keys safely.

Useful in scenarios like transaction processing, analytics aggregation, or inventory summing.

# Python
def merge_sum_dicts(*dicts):
    result = {}
    for d in dicts:
        for k, v in d.items():
            if k in result and isinstance(v, int):
                result[k] += v
            else:
                result[k] = v
    return result

print(merge_sum_dicts({'a': 1, 'b': 2}, {'a': 3, 'c': 4}))
Question 24

How do you handle nested dictionary updates without overwriting existing keys?

MEDIUM

Direct assignment may overwrite entire nested subkeys. Use recursive update functions or deep merge techniques.

This is important in configuration management, ETL data normalization, and merging JSON payloads where partial updates are common.

Python’s copy.deepcopy() combined with recursive merging ensures nested structures are updated safely without affecting the original dictionary.

Question 25

Which scenarios can lead to unexpected behavior when dictionaries contain mutable objects?

HARD
  • A Storing a list as a value and modifying it elsewhere
  • B Using deepcopy before modification
  • C Assigning the dictionary to another variable
  • D Iterating over keys safely

Mutable objects are stored by reference, so changes can propagate unexpectedly. Assigning dictionaries to new variables also copies references, not the data itself.

Question 26

Implement a dictionary-based word frequency counter.

MEDIUM

Dictionaries track word counts efficiently using get() with a default value.

This pattern is useful in text analytics, log parsing, and event stream aggregation.

# Python
text = 'python python dictionary example dictionary example'
frequency = {}
for word in text.split():
    frequency[word] = frequency.get(word, 0) + 1
print(frequency)
Question 27

Why are dictionary comprehensions preferred over loops in Python for data transformations?

MEDIUM

Dictionary comprehensions provide a concise, readable way to create or transform dictionaries in one expression.

They reduce boilerplate code and clearly convey filtering and transformation logic.

They are widely used for payload normalization, schema mapping, or preprocessing JSON data in backend systems.

Question 28

Which dictionary methods provide dynamic views of the dictionary's contents?

EASY
  • A keys()
  • B values()
  • C items()
  • D copy()

keys(), values(), and items() provide live views that reflect updates to the dictionary in real time. copy() creates a static snapshot.

Question 29

Write a Python function to flatten a nested dictionary into a single-level dictionary with dot-separated keys.

HARD

Recursive flattening is useful for converting nested JSON or configuration dictionaries into a flat structure suitable for analytics or CSV export.

Compound keys preserve hierarchy while keeping the structure flat for easy processing.

# Python
def flatten_dict(d, parent_key='', sep='.'):
    items = {}
    for k, v in d.items():
        new_key = f'{parent_key}{sep}{k}' if parent_key else k
        if isinstance(v, dict):
            items.update(flatten_dict(v, new_key, sep=sep))
        else:
            items[new_key] = v
    return items

nested = {'a': 1, 'b': {'c': 2, 'd': {'e': 3}}}
print(flatten_dict(nested))
Question 30

Implement a simple dictionary cache that returns default values if the key is missing.

MEDIUM

This pattern provides safe access to cached configuration values while falling back to defaults when a key is missing.

It is common in backend systems for runtime configuration overrides without losing default behavior.

# Python
defaults = {'host': 'localhost', 'port': 8080}
cache = {}

def get_cache(key):
    return cache.get(key, defaults.get(key))

cache['port'] = 9090
print(get_cache('port'))
print(get_cache('host'))