str.rindex()
The right-hand counterpart of index. It searches from the end, but the index it returns still counts from the start.
Demo
rindex finds the LAST place sub occurs. In "abcabc" the letter b sits at 1 and 4, so rindex returns 4 while index returns 1. Only the search direction is reversed — the number is still an ordinary left-counted index you can slice with directly. Absence raises ValueError, exactly as with index; use rfind if you would rather get -1.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| sub | str | yes | Substring to look for. The empty string is found at the far end of the searched range. |
| start | int | no (0) | Left boundary of the range searched. Matches before it are ignored. |
| end | int | no (len) | Right boundary. The slice searched is s[start:end]. |
Return value
int — Highest index where sub is found. Raises ValueError if it is absent — it never returns -1.
Common patterns
i = name.rindex(".") stem, ext = name[:i], name[i + 1:]
leaf = path[path.rindex("/") + 1:]
try: i = ref.rindex(":") except ValueError: raise ValueError("expected host:port")
Examples
Pitfalls
'hello'.rindex('l')
len(s) - s.rindex('l') - 1
'abcabc'.rindex('b', 2)
'abcabc'.rindex('b', 0, 4)
'hello'.rindex('z')
i = 'hello'.rfind('z') if i == -1: ...
When to use
- Splitting on the LAST separator — extensions, paths, host:port
- The separator is required and absence is an error
- You want the final occurrence and a left-counted index to slice with
- Absence is expected → rfind, which returns -1
- You want the FIRST occurrence → index or find
- Splitting a path → os.path or pathlib handles the edge cases for you
Notes
FAQ
Because rindex returns a position, not a distance from the end. Positions in Python strings count from 0 at the left regardless of which direction you searched, which is what makes the result directly usable in a slice.
s = 'hello' s[:s.rindex('l')] # 'hel'