If list index exists, do X
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
When code needs to access a list element only if a given index is valid, the safest approach is to make the rule explicit instead of hoping the index exists. In Python, the right technique depends on whether you want strict bounds checking, support for negative indices, or a fail-soft style that returns a default value.
The Direct Bounds Check
For normal non-negative indexing, the clearest test is:
This is explicit and fast. It states exactly what "exists" means for ordinary positive indices.
If index is out of range, the body simply does not run. That is usually the best choice when you want readable control flow and you already have the index in hand.
Negative Indices Change the Rule
Python allows negative indices, so -1 refers to the last element, -2 to the second-last, and so on. If your code should treat those as valid, the test needs to reflect Python's indexing rules more accurately:
That condition accepts both normal positive indices and Python-style negative ones.
This is one of the main reasons a generic statement like "if index exists" is incomplete. You need to decide whether negative indexing is part of the allowed behavior.
Use try and except When Access Is the Real Operation
If the index is usually valid and you are already about to read the value, try and except can be a good fit:
This approach is useful when the access itself is the point and an out-of-range index is exceptional rather than part of normal control flow.
It is less useful when you are doing many branches based on index validity, because the explicit bounds check is usually easier to read.
Wrap the Pattern in a Helper
If the same logic appears in many places, a helper function makes the code more consistent.
A strict non-negative version:
A Python-style version that also accepts negative indices:
That is often cleaner than repeating the same condition throughout the codebase.
Slicing Is Not the Same Thing
Sometimes people use slicing to avoid IndexError:
This returns an empty list instead of raising an error. That can be useful in some contexts, but it changes the type of the result. You no longer get a single element; you get a list of zero or one elements.
That means slicing is not a direct substitute for safe index access. Use it when you actually want slice semantics, not just a suppressed exception.
Choose the Style Based on Intent
A good rule of thumb is:
- use an explicit bounds check when index validity is part of ordinary branching
- use
tryandexceptwhen the access is expected to succeed most of the time - use a helper when the same rule appears repeatedly
- decide explicitly whether negative indices count as valid
That last point matters because Python makes negative indexing normal, while many other languages do not.
Common Pitfalls
The most common mistake is checking only index < len(items) and forgetting that negative numbers also pass that test, which can accidentally allow access from the end of the list. Another is using try and except everywhere even when a simple bounds check would make the logic clearer. Developers also sometimes use slicing to avoid IndexError and then forget that the result is a list rather than a single value. A final issue is writing helper functions without deciding whether they should honor Python's negative-index behavior or reject it.
Summary
- The clearest non-negative bounds check is
0 <= index < len(items). - If negative indices should be valid, use
-len(items) <= index < len(items). - '
tryandexcept IndexErroris useful when direct access is the main operation.' - Slicing avoids
IndexError, but it changes the result type. - Pick one index-validity rule and apply it consistently across the code.
Related reading
- if/else in a list comprehension
- ILookup interface vs IDictionary
- Immutable array in Java
- Immutable queue in Clojure
- Ignore certain exceptions when using Xcode's All Exceptions breakpoint
- Ignore 'Incorrect padding' error when base64 decoding
- ImmutableSortedDictionary range enumeration by key
- Implement a queue in which push_rear, pop_front and get_min are all constant time operations

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.