Python has no isint() function. To check if a variable is an integer, use isinstance:
isinstance(value, int) # True for 42, False for 3.14 and "42"
There’s one catch that bites almost everyone: isinstance(True, int) is also True, because bool is a subclass of int.
If booleans should not count, the check becomes isinstance(value, int) and not isinstance(value, bool).
Every result on this page was produced by running the code on Python 3.12.5, NumPy 2.5.3.
Python has no isint() function
It’s worth repeating, because a lot of people go looking for it: there is no isint(), no isInt and no is_int.
isinstance is the replacement, and you can wrap it in your own isint if the name helps:
value = 42
print(isinstance(value, int)) # True
print(isinstance(3.14, int)) # False
print(isinstance("42", int)) # False, it is a string
# there is no isint() built in, so this is what people mean by it
def isint(x):
return isinstance(x, int) and not isinstance(x, bool)
for item in (42, 3.14, "42", True, -7):
print(f"{str(item):<6} -> {isint(item)}")
Output:
True
False
False
42 -> True
3.14 -> False
42 -> False
True -> False
-7 -> True
isint that behaves the way people expect.The string "42" returns False, which is correct. It holds digits, but its type is str.
Checking the contents of a string is a different job, covered in checking whether a string is an integer or a float.
Why isinstance(True, int) returns True
Booleans are integers in Python. Not similar to integers, literally a subclass of them:
# bool is a SUBCLASS of int, so booleans pass an integer check
print("isinstance(True, int) :", isinstance(True, int), " <- surprising")
print("type(True) is int :", type(True) is int, " <- and this disagrees")
print("\nbool inherits from:", [cls.__name__ for cls in bool.__mro__])
print("True + True =", True + True)
print("True * 10 =", True * 10)
print("\nexcluding booleans explicitly:")
for item in (42, True, False, 0):
strict = isinstance(item, int) and not isinstance(item, bool)
print(f" {str(item):<6} isinstance={isinstance(item, int)!s:<6} strict={strict}")
Output:
isinstance(True, int) : True <- surprising
type(True) is int : False <- and this disagrees
bool inherits from: ['bool', 'int', 'object']
True + True = 2
True * 10 = 10
excluding booleans explicitly:
42 isinstance=True strict=True
True isinstance=True strict=False
False isinstance=True strict=False
0 isinstance=True strict=True
bool inherits from int, so True passes an integer check.That is why True + True evaluates to 2. Under the hood True is 1 and False is 0.
It matters in real code. A function that validates a quantity with isinstance(qty, int) will happily accept True and then treat it as 1.
isinstance(value, int)— accepts booleans, usually not what you want.isinstance(value, int) and not isinstance(value, bool)— rejects them.type(value) is int— also rejects them, but rejectsintsubclasses too.
isinstance vs type() for integer checks
isinstance accepts subclasses. type() is demands an exact match:
class Count(int): # a subclass of int
pass
n = Count(5)
print("isinstance(n, int) :", isinstance(n, int), " <- accepts subclasses")
print("type(n) is int :", type(n) is int, " <- exact type only")
print()
print("type(n) :", type(n).__name__)
print("n + 10 :", n + 10, "(it behaves exactly like an int)")
Output:
isinstance(n, int) : True <- accepts subclasses
type(n) is int : False <- exact type only
type(n) : Count
n + 10 : 15 (it behaves exactly like an int)
| Check | Plain int | True | int subclass |
|---|---|---|---|
isinstance(x, int) | Yes | Yes | Yes |
type(x) is int | Yes | No | No |
isinstance(x, int) and not isinstance(x, bool) | Yes | No | Yes |
Prefer isinstance as a rule. Subclasses of int behave like integers, so rejecting them is usually a bug rather than a feature.
The exception is exactly the boolean case, which is why the third row exists.
Checking if a variable is a number, not just an integer
When floats should pass too, name both types or reach for the numbers module:
import numbers
# int OR float OR anything else numeric
for value in (42, 3.14, True, complex(1, 2), "42", None):
is_number = isinstance(value, numbers.Number)
is_integral = isinstance(value, numbers.Integral)
print(f"{str(value):<8} Number={is_number!s:<6} Integral={is_integral}")
print()
# the plain-tuple version, which is enough most of the time
print("isinstance(3.14, (int, float)) :", isinstance(3.14, (int, float)))
print("isinstance(42, (int, float)) :", isinstance(42, (int, float)))
Output:
42 Number=True Integral=True
3.14 Number=True Integral=False
True Number=True Integral=True
(1+2j) Number=True Integral=False
42 Number=False Integral=False
None Number=False Integral=False
isinstance(3.14, (int, float)) : True
isinstance(42, (int, float)) : True
numbers.Number is the widest check. It accepts complex numbers as well, which is rarely what a form validator wants.
numbers.Integral means whole numbers specifically, and isinstance(x, (int, float)) covers the everyday case with no import.
Why isinstance fails on NumPy integers
NumPy has its own integer types, and they are not Python ints:
import numbers
import numpy as np
n = np.int64(5)
print("type :", type(n))
print("value :", n, "and it does arithmetic fine:", n + 1)
print()
print("isinstance(n, int) :", isinstance(n, int), " <- NOT a Python int")
print("isinstance(n, np.integer) :", isinstance(n, np.integer))
print("isinstance(n, numbers.Integral):", isinstance(n, numbers.Integral), " <- the portable check")
Output:
type : <class 'numpy.int64'>
value : 5 and it does arithmetic fine: 6
isinstance(n, int) : False <- NOT a Python int
isinstance(n, np.integer) : True
isinstance(n, numbers.Integral): True <- the portable check
np.int64 does integer arithmetic but fails isinstance(x, int).This is a common source of silent bugs. A value pulled out of a NumPy array or a pandas column fails your integer check even though it is obviously an integer.
numbers.Integral is the portable answer, since it covers both. See NumPy data types for why these separate types exist.
Checking if a float holds a whole number
5.0 is a float, but it may still be the whole number you’re after:
# a float that happens to hold a whole number
print("(5.0).is_integer() :", (5.0).is_integer())
print("(5.5).is_integer() :", (5.5).is_integer())
print()
def holds_whole_number(value):
"""True for 5 and 5.0, False for 5.5 and 'five'."""
if isinstance(value, bool):
return False
if isinstance(value, int):
return True
if isinstance(value, float):
return value.is_integer()
return False
for item in (5, 5.0, 5.5, True, "5"):
print(f" {str(item):<6} -> {holds_whole_number(item)}")
Output:
(5.0).is_integer() : True
(5.5).is_integer() : False
5 -> True
5.0 -> True
5.5 -> False
True -> False
5 -> False
is_integer() is a method on float, so call it only after confirming the type. On an int it does not exist in older versions.
The helper above handles all four cases in the order that matters, checking bool first so it can be rejected before the int branch catches it.
Checking if user input is an integer
input() always returns a string, so an isinstance check on it is always False:
# input() always returns a string, so type checks on it are meaningless
values = ["42", "-5", "3.14", " 7 ", "abc"]
print(f"{'text':<8} {'isdigit':>8} {'int() works':>13}")
for text in values:
try:
int(text)
parses = True
except ValueError:
parses = False
print(f"{text!r:<8} {text.isdigit()!s:>8} {parses!s:>13}")
print()
print("note ' 7 ': isdigit() is False but int() accepts it, because int() strips whitespace")
Output:
text isdigit int() works
'42' True True
'-5' False True
'3.14' False False
' 7 ' False True
'abc' False False
note ' 7 ': isdigit() is False but int() accepts it, because int() strips whitespace
' 7 ' fails isdigit() but converts fine.int() inside a try is the honest test, because it accepts exactly what Python accepts, including a leading minus and surrounding whitespace.
isdigit() is stricter and rejects negatives. The differences are laid out in the isdigit guide.
Which integer check should you use?
| Situation | Use |
|---|---|
| Plain integer check | isinstance(x, int) |
| Booleans must not pass | isinstance(x, int) and not isinstance(x, bool) |
| Integer or float | isinstance(x, (int, float)) |
| NumPy or pandas values | isinstance(x, numbers.Integral) |
| A float holding a whole number | x.is_integer() |
Text from input() | int(text) in a try |
Related type-checking guides on Python Guides:
- Check if a string is an integer or float
- Check if a variable is a boolean
- Check if a variable is a string
- The isdigit() string method
- NumPy data types
- Python variables explained
Frequently asked questions
How do I check if a variable is an integer in Python?
Use isinstance(value, int). The function is documented in the Python built-in functions reference.
Is there an isint() function in Python?
No. Python has no isint(), isInt or is_int. Use isinstance(value, int), or define your own one-line helper with that name.
Why does isinstance(True, int) return True?
bool is a subclass of int in Python, so every boolean is also an integer. That is also why True + True equals 2.
How do I check for an integer but exclude booleans?
isinstance(value, int) and not isinstance(value, bool), or type(value) is int if you also want to reject int subclasses.
What is the difference between isinstance and type()?
isinstance accepts subclasses, type(x) is int demands the exact type. isinstance is usually correct, except when you need to exclude booleans.
Why does isinstance fail on a NumPy integer?
np.int64 is not a Python int. Use isinstance(x, numbers.Integral), which accepts both.
How do I check if a string contains an integer?
Call int(text) inside a try block. isdigit() also works but rejects negative numbers.
Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn