You can use *args to pass an arbitrary number of arguments to a function. You can then use a loop to traverse the levels.
get_any_level(*keys):
d = table
for key in keys:
d = d[key]
return d
Now you have one function that can replace the three you had before:
print(get_any_level(first))
print(get_any_level(first, second1))
print(get_any_level(first, second2, third))
You can use this function to write to an arbitrary level as well:
get_any_level(first)[second1] = 17
A better way might be to have a separate function to write though:
def put_any_level(value, *keys):
get_any_level(*keys[:-1])[keys[-1]] = value
put_any_level(17, first, second1)
value
has to come first in the argument list unless you want it to be keyword-only because *keys
will consume all positional arguments. This is not necessarily a bad alternative:
def put_any_level(*keys, value):
get_any_level(*keys[:-1])[keys[-1]] = value
The keyword argument adds clarity:
put_any_level(first, second1, value=17)
But it will also lead to an error if you attempt to pass it as a positional argument, e.g. put_any_level(first, second1, 17)
.
Couple of minor points:
- It's conventional to use CamelCase only for class names. Variables and functions are conventionally written in lowercase_with_underscores.
- A function should generally do one thing, and do it well. In this case, I've split the task of finding the nested value from the task of displaying it by giving the function a return value.