describe_access(data, key, index) that attempts data[key][index] and returns the value on success, the string 'no such key' on KeyError, 'index out of range' on IndexError, and 'not indexable' on TypeError — three separate except branches.describe_access({'a': [1, 2]}, 'a', 5)'index out of range'
The list has no index 5.
describe_access({'a': 7}, 'a', 0)'not indexable'
Indexing an int raises TypeError.
Order of except blocks does not matter here — they are disjoint.
Return from inside each branch.