str.isidentifier()

Test whether a string has the SHAPE of a Python identifier — not whether you can use it as a variable name.

String methodPython 3.0+Live demo
Common call
if name.isidentifier():
Returns
True or False
Replaces
a manual regex like `^[a-zA-Z_][a-zA-Z0-9_]*$` — but the method is Unicode-aware
Watch out
reserved keywords (for, class, def, if, ...) return True — use keyword.iskeyword to filter them out
str.isidentifier()
bool

Demo

Live evaluation
Try:
Inputs
stringstrthe string to test
Output
'foo'.isidentifier()
True

isidentifier() checks the SHAPE of a Python identifier: starts with a Unicode letter or underscore, followed by letters, digits, or underscores. Empty returns False. THE surprise: reserved keywords like "for", "class", "def" all pass because they have identifier shape — but assigning to them would be a SyntaxError. For a full "can I use this as a variable name" test, combine with keyword.iskeyword().

Common patterns

Validate a Python-name-shaped input
The idiomatic check when accepting user-defined field names.
if not name.isidentifier():
    raise ValueError("must be a valid Python identifier")
Full "can I use this as a variable?" check
Combine with keyword.iskeyword to exclude reserved words.
import keyword
def is_usable_name(s):
    return s.isidentifier() and not keyword.iskeyword(s)
Safe attribute access
setattr can succeed even with non-identifier names — validate first for clean code.
if attr.isidentifier():
    setattr(obj, attr, value)
else:
    obj.__dict__[attr] = value

Examples

1. Basic
"foo".isidentifier()
Returns
True
2. With underscore
"user_name".isidentifier()
Returns
True
3. Leading underscore
"_hidden".isidentifier()
Returns
True
4. With digit
"name123".isidentifier()
Returns
True
5. Starts with digit
"1abc".isidentifier()
Returns
False
6. Contains space
"user name".isidentifier()
Returns
False
7. Contains dash
"my-name".isidentifier()
Returns
False
8. Keyword is True
"for".isidentifier()
Returns
True # surprising but correct
9. Unicode
"café".isidentifier()
Returns
True
10. Empty is False
"".isidentifier()
Returns
False

Pitfalls

1. Reserved keywords PASS isidentifier
The most common surprise. `"for".isidentifier()` returns True — the string HAS identifier shape. Python enforces the keyword restriction at parse time, not at method call. For a "could I use this as a variable name" check, combine with keyword.iskeyword().
Accepts keyword
"class".isidentifier()
True
Filter keywords
import keyword
"class".isidentifier() and not keyword.iskeyword("class")
False
2. Dashes are NOT allowed — even in HTML-style attributes
Python identifiers use underscores, not dashes. `"my-name"` is not a valid Python identifier. This bites people converting HTML attribute names or CSS variable names.
Dash rejected
"my-name".isidentifier()
False
Underscore instead
"my_name".isidentifier()
True
3. First character rules are STRICTER
The first character must be a Unicode letter or underscore. Digits and most punctuation cannot start an identifier. This is why leading-digit strings fail even if they contain otherwise-valid characters.
Digit start rejected
"1st".isidentifier()
False
Prefix underscore
"_1st".isidentifier()
True
4. Unicode identifiers are allowed — sometimes surprisingly
Python 3 allows Unicode letters in identifiers. Names like "café" and "π" are valid identifiers. This can be a security or readability concern in shared codebases.
Unicode passes
"π".isidentifier()
True
ASCII-only check
name.isascii() and name.isidentifier()
False on non-ASCII

When to use

Use it
  • Validating user-provided field or attribute names
  • Safety check before dynamic attribute access
  • Config-file key validation
  • Combining with keyword.iskeyword for full "usable name" check
Reach for something else
  • You need to reject reserved words → also check keyword.iskeyword
  • You need ASCII-only names → combine with str.isascii
  • You want lowercase snake_case only → regex or a custom validator
  • Rich Unicode restrictions → third-party library or explicit character set

Notes

Complexity
O(n) — one linear scan
Return
bool — True or False
CPython impl
Objects/unicodeobject.c :: unicode_isidentifier — uses the same rules as the parser
Memory
No allocation
Thread-safe
Yes — strings are immutable

FAQ

Because isidentifier tests the SHAPE — starts with a letter or underscore, followed by letters, digits, or underscores. "for" matches that shape. Python rejects it as a variable name at parse time, not at method-call time. For a "usable as a variable name" check, add `keyword.iskeyword` to the test.

History

3.0
isidentifier() introduced along with Unicode-aware identifier rules (PEP 3131).