str.isalnum()
The letters-OR-digits check — the union of isalpha and (isdigit / isnumeric / isdecimal).
Common call
if token.isalnum():
Returns
True or False
Replaces
a manual loop of `if not (ch.isalpha() or ch.isdigit()): return False`
Watch out
empty string → False; underscores and spaces both break it
str.isalnum()
→ bool
Demo
Live evaluation
Try:
Inputs
stringstrthe string to test
Output
'hello'.isalnum()
True
isalnum() returns True when EVERY character is either a letter or a digit AND the string is non-empty. Spaces, underscores, hyphens, dots, and any other punctuation all break it. "Letter" and "digit" are Unicode-aware — accented letters and non-Latin scripts pass, but so do numeric characters from other systems. The empty string returns False by convention.
Common patterns
Loose identifier check
Real identifiers also allow underscores; for a proper check use str.isidentifier().
if not token.isalnum(): raise ValueError("letters and digits only")
Reject punctuation and whitespace
A quick sanity check on user-typed short codes.
if not code.isalnum(): return False
Combine with isdigit for "has at least one letter"
A common validation shape.
if token.isalnum() and not token.isdigit(): ... # has letters, may have digits
Examples
1. Letters only
"hello".isalnum()
Returns
True2. Digits only
"12345".isalnum()
Returns
True3. Mixed
"hello123".isalnum()
Returns
True4. Space breaks it
"hello world".isalnum()
Returns
False5. Unicode passes
"café1".isalnum()
Returns
True6. Underscore fails
"user_name".isalnum()
Returns
False7. Empty is False
"".isalnum()
Returns
False8. Punctuation fails
"a.b".isalnum()
Returns
FalsePitfalls
1. Empty string returns False, not True
Same rule as isalpha and isdigit — the empty case is False by convention. isalnum requires at least one character.
Wrong expectation
"".isalnum()
False
Read the contract
"".isalnum() # always False "".isdigit() # always False "".isspace() # always False
documented behaviour
2. Underscores are NOT alphanumeric
Underscore is punctuation, not a letter or digit. Passwords, IDs, and identifiers that contain underscores fail isalnum. For proper identifier checking, use str.isidentifier().
Fails on _
"user_id".isalnum()
False
Identifier check
"user_id".isidentifier()
True
3. Spaces are NOT alphanumeric
A single space breaks isalnum. Split first if multi-token input is legitimate.
Multi-token fails
"hello world 123".isalnum()
False # spaces
Per token
all(t.isalnum() for t in text.split())
True
4. Unicode "digits" include surprising code points
Roman numerals, superscripts, and fractions pass isnumeric AND isalnum — a quirk if you expected ASCII digits only. Combine with .isascii() when that matters.
Too permissive
"Ⅳ".isalnum()
True # Roman numeral
ASCII only
name.isascii() and name.isalnum()
True only for ASCII letters/digits
When to use
Use it
- Quick validation that a token has no punctuation or whitespace
- Loose "letters or digits, that's it" check on short codes
- Combined with .split() for word-by-word validation
- Composing with isalpha / isdigit / isspace for finer checks
Reach for something else
- Proper identifier check — use str.isidentifier() (allows underscores, forbids leading digits)
- ASCII-only validation → combine with .isascii()
- Rich validation (length, format) → use a regex or validator library
- Values that legitimately contain spaces → split first
Notes
Complexity
O(n) — one linear scan
Return
bool — True or False
CPython impl
Objects/unicodeobject.c :: unicode_isalnum
Memory
No allocation
Thread-safe
Yes — strings are immutable
FAQ
Underscore is punctuation, not a letter or digit. For identifier-shaped strings (which include underscores), use str.isidentifier() instead.
History
1.0
isalnum() has been part of str since Python 1.0.
3.0
Full Unicode support — accepts letters and digits from any script per Unicode categorization.