bytes.isalpha and the is* family()

Eight predicates that share one rule set. The important difference from their str counterparts: these know only ASCII, so no accented or non-Latin byte ever counts as a letter.

Bytes methodsPython 3.0+Live demo
Common call
data.isdigit()
Returns
bool — True only if EVERY byte qualifies
Replaces
all(chr(b).isdigit() for b in data)
Watch out
empty bytes is False for seven of the eight — isascii is the exception
bytes.isalnum() | isalpha() | isascii() | isdigit() | islower() | isspace() | istitle() | isupper()
→ bool

Demo

Live evaluation
Try:
Inputs
sstrdata (encoded as utf-8)
methodstrisalpha, isdigit, isupper, …
Output
getattr(bytes('abc', 'utf-8'), 'isalpha')()
True

Each predicate asks whether EVERY byte qualifies, so one bad byte makes the whole answer False. The two accented cases together tell the real story: "héllo" is not isalpha, because the accented character is stored as two non-ASCII bytes that are not letters as far as bytes is concerned — and it is not isascii either, for the same reason. The str versions of these methods answer True for both, which is exactly the gap to watch when converting text code to binary.

Common patterns

Validate a numeric field
Cheaper than a try/except around int() when the data is untrusted.
if not field.isdigit():
    raise ValueError("expected digits")
Check a payload is plain ASCII
isascii is the fast pre-check before decoding.
if data.isascii():
    text = data.decode('ascii')
Reject unexpected whitespace
isspace identifies padding or blank records.
records = [r for r in rows if not r.isspace()]

Examples

1. Letters
b'abc'.isalpha()
Returns
True
2. Digits
b'123'.isdigit()
Returns
True
3. Mixed is alnum
b'abc123'.isalnum()
Returns
True # but isalpha is False
4. Empty is False
b''.isalpha()
Returns
False
5. Empty IS ascii
b''.isascii()
Returns
True # the exception
6. Non-ASCII
'é'.encode().isalpha()
Returns
False

Pitfalls

1. They are ASCII-only, unlike the str versions
The difference that matters most. "héllo".isalpha() is True as text but False as UTF-8 bytes, because the accented character becomes two bytes that are not ASCII letters. Converting text-validation code to binary silently changes the answers.
bytes says no
'héllo'.encode().isalpha()
False
Decode first
'héllo'.isalpha()
True
2. Empty input is False — except for isascii
Seven of the eight return False for empty bytes, because "every byte qualifies" is not satisfied by having none. isascii breaks the pattern and returns True, which is easy to forget in a validation chain.
Inconsistent
b''.isalpha(), b''.isascii()
(False, True)
Test length too
if data and data.isalpha():
explicit
3. isdigit does not mean int() will work
A leading minus sign, a decimal point or surrounding whitespace all make isdigit False while int() or float() would still succeed — and isdigit True does not guarantee the value fits anywhere sensible.
Negative rejected
b'-5'.isdigit()
False
Try the conversion
try:
    n = int(b'-5')
except ValueError:
    ...
-5
4. islower and isupper ignore non-letters
They ask whether the CASED bytes are all one case, so digits and punctuation are simply skipped. A buffer with no letters at all is neither lower nor upper.
No letters
b'123'.islower(), b'123'.isupper()
(False, False)
Check for letters
b'a1'.islower()
True # the digit is ignored
5. istitle has its own definition of a word
A word starts after any non-letter, so punctuation and digits begin new words. That makes strings like "Abc1Def" title case in ways people rarely expect.
Surprising True
b'Abc Def'.istitle()
True
Check explicitly
data == data.title()
same rule, stated

When to use

Use it
  • Validating binary fields before parsing them
  • A fast isascii check before decoding
  • Rejecting blank or whitespace-only records
Reach for something else
  • The data is text → decode first; the str versions understand Unicode
  • Deciding whether int() will succeed → just try the conversion
  • Anything involving non-ASCII letters — these will always say no

Notes

Complexity
O(n) — every byte is examined, with an early exit on the first failure
Return
A bool; never raises
CPython impl
Objects/bytesobject.c :: bytes_isalpha and siblings
Memory
No allocation
Thread-safe
Yes — bytes are immutable

FAQ

Because bytes knows nothing about Unicode. In UTF-8 an accented character is two bytes, neither of which is an ASCII letter, so the test fails. The str version decodes first and answers True.

'é'.encode().isalpha()   # False
'é'.isalpha()            # True

History

3.0
The is* family arrived with the bytes type in the text/binary split.
3.7
isascii added to str, bytes and bytearray.