str.islower()

Check that a string is entirely lowercase — but only among characters that have a case.

String methodPython 1.0+Live demo
Common call
if name.islower():
Returns
True or False
Replaces
`s == s.lower()` — but islower needs at least ONE cased character
Watch out
not islower() != isupper(); digits-only string returns False
str.islower()
bool

Demo

Live evaluation
Try:
Inputs
stringstrthe string to test
Output
'hello'.islower()
True

islower() returns True only when the string contains at least one CASED character AND every cased character is lowercase. Non-cased characters (digits, spaces, punctuation, non-cased scripts) are IGNORED — they neither pass nor fail the check. A string with ONLY digits or ONLY punctuation returns False because there is no cased character to check.

Common patterns

Validate an all-lowercase input
Quick check that user input matches an all-lowercase convention.
if not username.islower():
    raise ValueError("username must be lowercase")
Not the same as `s == s.lower()`
The lower() equality includes digits and symbols; islower() requires a cased character.
has_lower_intent = s.islower()          # False for "123"
reads_as_lower   = s == s.lower()        # True  for "123"
Skip already-lowercase strings
Avoid redundant work in transformation pipelines.
if not text.islower():
    text = text.lower()

Examples

1. All lower
"hello".islower()
Returns
True
2. Mixed case
"Hello".islower()
Returns
False
3. All upper
"HELLO".islower()
Returns
False
4. Lower + digits
"hello123".islower()
Returns
True # digits are non-cased
5. Lower + spaces
"hello world".islower()
Returns
True
6. Digits only
"12345".islower()
Returns
False # no cased char
7. Unicode
"café".islower()
Returns
True
8. Empty is False
"".islower()
Returns
False

Pitfalls

1. Requires at least one cased character
A string with only digits or only punctuation returns False — there is no cased character to verify. Same rule as isupper(); different rule than isspace or isdigit that just checks emptiness.
Digits-only False
"12345".islower()
False
Combined test
s == s.lower() and any(c.isalpha() for c in s)
True on lowercase text
2. not islower() is NOT isupper()
Both islower() and isupper() require at least one cased character AND checking their case. A mixed-case string returns False from both. A digits-only string also returns False from both. Do not treat them as complements.
Assumed complement
"Hello".islower() or "Hello".isupper()
False # neither, not both
Explicit check
all(c.islower() or not c.isalpha() for c in s)
stricter intent
3. Empty string returns False, not True
Same rule across the is* family — empty is always False. Ignoring the "at least one" requirement gives you a bug that manifests only on edge cases.
Wrong expectation
"".islower()
False
Guard first
s and s.islower()
covers the empty case
4. Non-cased scripts confuse the intent
CJK ideographs, digits, punctuation — none are cased. A string of only Chinese characters returns False from islower(), which is often surprising.
CJK is False
"漢字".islower()
False # not cased
Check for cased first
any(c.isalpha() for c in s)
guards against non-cased scripts

When to use

Use it
  • Validating an all-lowercase username, ID, or convention
  • Skipping redundant .lower() calls in transformation pipelines
  • Composing with isupper / isalpha / isdigit for finer case checks
  • Testing that a normalized value is in its canonical form
Reach for something else
  • `s == s.lower()` is subtly different — chooses when digits should pass
  • Case-insensitive comparison → str.casefold
  • Titlecase check → str.istitle
  • Value has non-Latin scripts and case matters → normalize first

Notes

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

FAQ

Because digits are not cased characters. islower() requires at least one cased character AND every cased character to be lowercase. With no cased characters, the "at least one" condition fails.

History

1.0
islower() has been part of str since Python 1.0.
3.0
Full Unicode support — checks per Unicode general category and case mapping.