The Path Inward
A medium Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.
- Domain
- Python
- Difficulty
- medium
- Seniority
- L4
Problem
A service config nests sections inside sections, and config holds one such tree. Given path, a list of keys naming a single setting's route from the top level inward, return that setting's value. Return None the moment the path can no longer be followed, including when it runs into a plain value before the keys run out.
Every setting hides a few levels down. Follow the route, or come back empty.
Example 1
Input:
config = {"db":{"pool":{"max_conns":42}}}, path = ["db","pool","max_conns"]Output:
42
Example 2
Input:
config = {"cache":{"ttl":10}}, path = ["cache","ttl"]Output:
10
Worked solution and explanation
What this really is
Strip the config costume off and this is a guarded walk down a chain of dict lookups. Everyone gets the happy path: start at the top, grab path[0], then path[1], keep going. The part that actually separates people is the failure: somewhere mid-route a key is missing, or worse, the value you just landed on is a plain int or string and the NEXT key tries to index into it. Miss that second case and your function does not return None, it blows up with a TypeError deep inside a config load and takes the whole service start with it.
How to walk it
Step 1: Carry one cursor down the tree
Hold one moving reference, starting at config itself. You are not recursing here; you are sliding a pointer down one level at a time, and that single variable is the only state you need.
Step 2: Take one key at a time
For each key in path, you want to step into the next section. But before you index, you have to know two things are true: what you are holding is still a dict, and this key actually lives in it.
Step 3: Bail out the moment the route dies
The instant either check fails, hand back None and stop. This is the whole game: a missing key and a scalar-where-a-dict-should-be both mean the route died, and both have to exit the same quiet way instead of throwing.
The solution
def nested_access(config, path):
current = config
for key in path:
if not isinstance(current, dict) or key not in current:
return None
current = current[key]
return currentCommon follow-up questions
- How would you support a caller-supplied default instead of always returning None? (Tests adding a default parameter to the function signature.)
- What changes if a path segment can be a list index, like reaching into items then position 0? (Tests extending traversal to handle both dict key access and list index access.)
- How would you write the `deep_set` twin that creates the path when it does not exist yet? (Tests building nested dicts on the fly with setdefault chaining.)