Checking a variable’s type in Python takes one of two built-ins. type(x) tells you exactly what x is, and isinstance(x, SomeType) tells you whether it’s that type or a subclass of it:
price = 19.99
type(price) # <class 'float'>
isinstance(price, float) # True
isinstance(price, (int, float)) # True: either type
I tested everything below on Python 3.12.5 with NumPy 2.5.3; the screenshots are the real Command Prompt output.
Use isinstance() for checks in your code and type() when you want to see or print the type. Below you’ll see why, plus numbers, floats, dates and the surprise that True counts as an integer.
Using type() to see a variable’s type
type() returns the class of the object. Add .__name__ when you only want the name as text:
values = [42, 19.99, "Austin", True, None, [1, 2], {"TX": 1}]
for v in values:
print(f"{v!r:12} -> {type(v).__name__}")
print(type(42) is int) # compare a type with `is`
Output:
42 -> int
19.99 -> float
'Austin' -> str
True -> bool
None -> NoneType
[1, 2] -> list
{'TX': 1} -> dict
True

type() on seven common values. Note that None has its own type, NoneType.When you compare types directly, use is, as in type(x) is int. There’s exactly one int class, so identity is the right test.
type() vs isinstance(): which should you use?
isinstance() accepts subclasses and a tuple of types, which makes it the better choice almost every time you’re making a decision in code:
price = 19.99
print(isinstance(price, float)) # True
print(isinstance(price, (int, float))) # either one: True
print(isinstance("19.99", (int, float))) # a string isn't a number
# isinstance also accepts subclasses, type() doesn't
class Discount(float):
pass
d = Discount(0.15)
print("isinstance:", isinstance(d, float), "| type() is float:", type(d) is float)
Output:
True
True
False
isinstance: True | type() is float: False
Discount is a kind of float, so isinstance() says yes while type() is float says no. Code that rejects subclasses usually breaks for no good reason. isinstance and issubclass in Python has more examples.
Why does isinstance(True, int) return True?
Because bool is a subclass of int: True behaves like 1 and False like 0. That’s useful for counting, but it means a plain isinstance(x, int) lets booleans through:
print("isinstance(True, int):", isinstance(True, int)) # bool is a subclass of int
print("type(True) is int :", type(True) is int)
print("True + True :", True + True)
def is_int(value):
return isinstance(value, int) and not isinstance(value, bool)
for v in [7, True, 7.0]:
print(f"is_int({v!r}) -> {is_int(v)}")
Output:
isinstance(True, int): True
type(True) is int : False
True + True : 2
is_int(7) -> True
is_int(True) -> False
is_int(7.0) -> False

True + True is 2. The helper excludes booleans explicitly.If a form field or JSON value should be a whole number, exclude bool as shown. Checking if a variable is an integer and checking for a boolean go further.
How to check if a variable is a number in Python
numbers.Number covers every numeric type, including Decimal, complex numbers and your own classes, as long as they register. Exclude bool again unless you want it:
import numbers
from decimal import Decimal
def is_number(value):
return isinstance(value, numbers.Number) and not isinstance(value, bool)
for v in [7, 19.99, Decimal("19.99"), 2 + 3j, "19.99", True, None]:
print(f"{v!r:18} -> {is_number(v)}")
print("Decimal is a Real?", isinstance(Decimal("19.99"), numbers.Real))
Output:
7 -> True
19.99 -> True
Decimal('19.99') -> True
(2+3j) -> True
'19.99' -> False
True -> False
None -> False
Decimal is a Real? False

None are rejected. Decimal is a number but not a numbers.Real.That last line catches people out: Decimal deliberately isn’t registered as Real, so check numbers.Number if money values stored as Decimal should pass.
Check if a variable is a float
isinstance(x, float) answers the type question. Whether a string could become a float is a different question, and float() inside try answers it best:
for v in [19.99, 20.0, 20, "19.99"]:
print(f"{v!r:8} isinstance float: {isinstance(v, float)}")
print((20.0).is_integer()) # a float with no fractional part
def looks_like_float(text):
try:
float(text)
return True
except ValueError:
return False
print(looks_like_float("19.99"), looks_like_float("$19.99"), "12.5".isdigit())
Output:
19.99 isinstance float: True
20.0 isinstance float: True
20 isinstance float: False
'19.99' isinstance float: False
True
True False False
"12.5".isdigit() is False because the dot isn’t a digit, which is why string methods are the wrong tool here. Checking if a string is an integer or float covers that case properly.
Check if a variable is a datetime or a date
Here’s a subtle one: datetime is a subclass of date, so every datetime also passes isinstance(x, date). Check for the subclass first:
from datetime import date, datetime
launch = datetime(2026, 10, 8, 14, 0) # a date AND a time
holiday = date(2026, 11, 26) # Thanksgiving 2026
print("isinstance(launch, date) :", isinstance(launch, date)) # True!
print("isinstance(launch, datetime):", isinstance(launch, datetime))
print("type(launch) is date :", type(launch) is date)
print("isinstance(holiday, datetime):", isinstance(holiday, datetime))
def kind(value):
if isinstance(value, datetime): # check the subclass FIRST
return "datetime"
if isinstance(value, date):
return "date"
return "neither"
print(kind(launch), kind(holiday), kind("2026-11-26"))
Output:
isinstance(launch, date) : True
isinstance(launch, datetime): True
type(launch) is date : False
isinstance(holiday, datetime): False
datetime date neither

datetime first keeps the two apart.The same “most specific first” rule applies to bool and int, and to any class hierarchy of your own.
Checking types with match-case (Python 3.10+)
When you branch on several types, structural pattern matching reads more cleanly than a chain of isinstance() calls:
def describe(value):
match value:
case bool(): # before int, because bool is an int
return "yes/no"
case int() | float():
return "number"
case str():
return "text"
case None:
return "missing"
case _:
return type(value).__name__
print([describe(v) for v in [True, 7, 2.5, "TX", None, [1]]])
Output:
['yes/no', 'number', 'number', 'text', 'missing', 'list']
Put bool() before int(), for the reason you’ve already seen. Otherwise True would match the int() case.
NumPy types: why np.int64 isn’t an int
Values that come out of NumPy arrays have NumPy types. np.float64 happens to subclass float, but np.int64 doesn’t subclass int:
import numbers
import numpy as np
count = np.int64(5)
price = np.float64(19.99)
print("isinstance(np.int64, int) :", isinstance(count, int))
print("isinstance(np.int64, Integral) :", isinstance(count, numbers.Integral))
print("isinstance(np.float64, float) :", isinstance(price, float))
print("np.issubdtype(int64, integer) :", np.issubdtype(count.dtype, np.integer))
Output:
isinstance(np.int64, int) : False
isinstance(np.int64, Integral) : True
isinstance(np.float64, float) : True
np.issubdtype(int64, integer) : True
If your code receives values from NumPy or pandas, check against numbers.Integral or numbers.Real rather than int and float, and both kinds will pass.
How to check the type of a variable: cheat sheet
| Question | Check |
|---|---|
| What type is it? | type(x) or type(x).__name__ |
| Is it a string? | isinstance(x, str) |
| Is it a whole number (not bool)? | isinstance(x, int) and not isinstance(x, bool) |
| Is it any number? | isinstance(x, numbers.Number) |
| Is it a float? | isinstance(x, float) |
| Can this text become a float? | float(text) inside try |
| Datetime or plain date? | Check datetime first, then date |
| Is it None? | x is None |
| Several types at once | isinstance(x, (int, float)) |
For None specifically, use is rather than a type check; checking if a variable is None explains why. More type-checking guides:
- isinstance() and issubclass() in Python
- Check if a variable is a string
- Check if a variable is an integer
- Check if a variable is a boolean
- Mutable vs immutable types in Python
Frequently asked questions
How do I check the type of a variable in Python?
Use type(x) to see it, or isinstance(x, SomeType) to test it. isinstance() is the better choice for checks because it accepts subclasses.
What’s the difference between type() and isinstance()?
type() returns the exact class. isinstance() returns True for that class or any subclass, and accepts a tuple of types.
Why is isinstance(True, int) True?
bool is a subclass of int in Python. Add and not isinstance(x, bool) when booleans shouldn’t count.
How do I check if a variable is a number?
isinstance(x, numbers.Number) covers int, float, complex, Decimal and Fraction. Exclude bool if needed.
How do I check if a variable is a datetime?
isinstance(x, datetime). Because datetime is a subclass of date, test for datetime before date.
Can I check a variable’s type with ==?
type(x) == int works, but type(x) is int is the idiomatic form, and isinstance() is usually better still. The isinstance() documentation describes the exact rules.

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