tuple.index()

The other half of the two-method tuple interface. Unlike str.find there is no -1 variant — absence is always an exception.

Tuple methodPython 2.6+Live demo
Common call
t.index(value)
Returns
int — the first position, counting from 0
Replaces
next(i for i, x in enumerate(t) if x == value)
Watch out
raises ValueError when absent; there is no find() for tuples
tuple.index(value[, start[, stop]])
int

Demo

Live evaluation
Try:
Inputs
itemstupletuple items, comma separated
valueAnyvalue to locate
Output
tuple(['a', 'b', 'c']).index('b')
1

index scans left to right and stops at the first element equal to the value, returning its position. With duplicates you always get the earliest one. A value that is not present raises ValueError — there is no tuple equivalent of str.find that would hand back -1, so absence must be handled with try or checked first with the in operator.

Parameters

NameTypeRequiredDescription
valueAnyyesValue to locate. Compared with ==, so equal-but-not-identical objects match.
startintno (0)Where to begin searching. The returned index is still absolute.
stopintno (len)Where to stop searching, exclusive.

Return value

intLowest index whose element equals value. Raises ValueError if there is no match.

Common patterns

Look up a column by name
A header tuple turns names into positions for the rows beneath it.
col = header.index("email")
value = row[col]
Guard with in
Cheaper to read than a try block when absence is expected.
if value in t:
    i = t.index(value)
Find the next match after a position
start skips earlier hits without slicing a copy.
second = t.index(value, t.index(value) + 1)

Examples

1. Middle element
('a', 'b', 'c').index('b')
Returns
1
2. First element
('a', 'b', 'c').index('a')
Returns
0
3. First of two
('a', 'b', 'a').index('a')
Returns
0
4. Absent raises
('a', 'b').index('z')
Returns
ValueError: tuple.index(x): x not in tuple
5. Empty raises
().index('a')
Returns
ValueError: tuple.index(x): x not in tuple
6. Search from 1
('a', 'b', 'a').index('a', 1)
Returns
2

Pitfalls

1. There is no find() for tuples
Strings offer find as a non-raising alternative; sequences do not. Every absent lookup is an exception, so it must be caught or pre-checked.
No such method
('a', 'b').find('z')
AttributeError: 'tuple' object has no attribute 'find'
Check first
i = t.index('z') if 'z' in t else -1
-1
2. Only the FIRST match is reported
With duplicates, index says nothing about how many there are or where the others sit. Code that assumes uniqueness silently reads the wrong row.
Hides duplicates
('a', 'b', 'a').index('a')
0 # the second is invisible
Enumerate for all
[i for i, x in enumerate(t) if x == 'a']
[0, 2]
3. in followed by index scans twice
Readable, but it walks the tuple once to test and again to locate. On hot paths catch the exception instead, or use enumerate once.
Two scans
if v in t:
    i = t.index(v)
O(2n)
One scan
try:
    i = t.index(v)
except ValueError:
    i = -1
O(n)

When to use

Use it
  • Mapping a header name to a column position
  • Locating a known-present value in a fixed record
  • Any place you would write next(i for i, x in enumerate(t) ...)
Reach for something else
  • Absence is expected and normal → test with in first
  • You need every position → enumerate with a comprehension
  • You want the COUNT → tuple.count

Notes

Complexity
O(n) worst case; stops at the first match, so often much less
Return
A non-negative int; absence raises rather than returning -1
CPython impl
Objects/tupleobject.c :: tupleindex
Memory
No allocation — compares in place, and start avoids slicing
Thread-safe
Yes — tuples are immutable

FAQ

Because -1 is a valid index in Python — it means the last element. Returning it for "not found" would make t[t.index(v)] quietly give the wrong element instead of failing. str.find can get away with -1 only because callers are expected to check.

t = ('a', 'b')
# if index returned -1, t[-1] would look like a match

History

2.6
tuple.index and tuple.count added, aligning tuple with the Sequence interface.