Question
How can you check whether an object is a given type in Python, including whether it inherits from that type?
For example, how can you determine whether an object o should be treated as a str?
o = "hello"
More generally:
- How do you check whether an object is exactly a specific type?
- How do you check whether an object is an instance of a type or any subclass of that type?
This question is about checking Python object types correctly. It is not about converting strings to numbers or deciding whether a string like "1" should count as an integer.
Short Answer
By the end of this page, you will understand the standard Python ways to check an object’s type: when to use isinstance(), when type() is appropriate, and how inheritance affects the result. You will also see common mistakes, practical examples, and how type checks are used in real Python code.
Concept
In Python, the canonical way to check whether an object behaves like a given type is usually isinstance(obj, SomeType).
isinstance(o, str)
This returns True if o is:
- exactly a
str, or - an instance of a subclass of
str
That matters because Python supports inheritance. A class can extend another class, and objects of the child class should often be accepted anywhere the parent type is expected.
If you want to check whether an object is exactly one specific type and not a subclass, use:
type(o) is str
or equivalently:
type(o) == str
However, type(o) is str is typically preferred over == for exact type identity.
Why this matters
Type checks appear in real programs when:
- validating function arguments
- handling different input formats
- writing APIs and libraries
- branching logic based on object categories
- safely processing user data
But Python generally prefers duck typing when possible: instead of asking "is this a string?", code often asks "can this object be used like a string?" Still, when you really do need a type check, isinstance() is usually the right tool.
The key rule
- Use
isinstance(obj, T)when subclasses should count. - Use
type(obj) is Tonly when you need an exact type match.
Mental Model
Think of a class as a job title and inheritance as specialization.
stris like the job title Writer.- A subclass of
stris like Technical Writer.
If a task says, "Anyone who is a Writer can do this," then both Writer and Technical Writer should qualify. That is what isinstance() does.
If the rule says, "Only someone with the exact title Writer, not any specialized version," then you need an exact match. That is what type(obj) is str does.
So:
isinstance()asks: Does this object belong to this family of types?type() isasks: Is this object exactly this one type?
Syntax and Examples
The two most common approaches are:
1. Check for a type or subclass with isinstance()
o = "hello"
print(isinstance(o, str))
Output:
True
This is the standard approach in Python.
2. Check for the exact type with type()
o = "hello"
print(type(o) is str)
Output:
True
This only matches if o is exactly a str.
Example with inheritance
class MyString(str):
pass
value = MyString("hello")
print(isinstance(value, str)) # True
print(type(value) is str) # False
print(type(value) is MyString) # True
Explanation:
valueis not exactly astr- it is a
MyString - but
MyStringinherits fromstr, soisinstance(value, str)isTrue
Checking against multiple types
isinstance() can also accept a tuple of types:
value = 10
print(isinstance(value, (int, float)))
Output:
True
This is useful when several types are acceptable.
A common function example
def shout(text):
if not isinstance(text, str):
raise TypeError("text must be a string")
return text.upper()
print(shout("hello"))
This validates the input before using string methods.
Step by Step Execution
Consider this example:
class Animal:
pass
class Dog(Animal):
pass
pet = Dog()
print(isinstance(pet, Dog))
print(isinstance(pet, Animal))
print(type(pet) is Dog)
print(type(pet) is Animal)
Here is what happens step by step:
Animalis defined.Dogis defined as a subclass ofAnimal.pet = Dog()creates aDogobject.isinstance(pet, Dog)checks whetherpetis aDogor subclass ofDog.- Result:
True
- Result:
isinstance(pet, Animal)checks whetherpetis anAnimalor subclass ofAnimal.- Since
Doginherits fromAnimal, result:True
- Since
type(pet) is Dogchecks the exact type.petwas created fromDog, so result:True
type(pet) is Animalchecks whether the exact type isAnimal.- It is not;
petis aDog, so result:False
- It is not;
Output:
True
True
True
False
This example shows the difference clearly:
isinstance()follows inheritancetype() isdoes not
Real World Use Cases
Input validation
A function may require text input:
def save_username(name):
if not isinstance(name, str):
raise TypeError("name must be a string")
# save name
Accepting several numeric types
def square(x):
if not isinstance(x, (int, float)):
raise TypeError("x must be numeric")
return x * x
Handling data from APIs
When parsing JSON-like data, you may need to confirm the shape of a value:
def process_payload(data):
if not isinstance(data, dict):
raise TypeError("data must be a dictionary")
Working with custom class hierarchies
class Shape:
pass
class Circle(Shape):
pass
class Square(Shape):
pass
def draw(shape):
if not isinstance(shape, Shape):
raise TypeError("Expected a Shape")
This lets Circle and Square both pass because they are both kinds of Shape.
Real Codebase Usage
In real projects, developers often use type checks in controlled places rather than everywhere.
Guard clauses
A common pattern is to reject invalid input early:
def normalize_text(value):
if not isinstance(value, str):
raise TypeError("value must be a string")
return value.strip().lower()
This keeps the rest of the function simpler.
Validation at module boundaries
Type checks are common where data enters the system:
- API request handlers
- file readers
- command-line argument processing
- deserialization code
Once data is validated, the rest of the code can assume correct types.
Accepting abstract parent types
Instead of checking for one exact class, code often checks for a parent type so subclasses also work:
def handle_error(err):
if isinstance(err, Exception):
print(f"Error: {err}")
This is flexible and works with built-in and custom exception classes.
Early return patterns
def format_label(value):
if value is None:
return ""
if not isinstance(value, str):
return str(value)
return value.strip()
Prefer capability checks when suitable
Sometimes developers avoid strict type checks and instead rely on behavior:
def print_upper(text):
print(text.upper())
This works for any object that provides .upper(), not just str. That style is often more Pythonic when exact type is not important.
Common Mistakes
1. Using type() when inheritance should be allowed
Broken idea:
class MyString(str):
pass
value = MyString("hello")
print(type(value) is str) # False
If your code should accept subclasses, use:
print(isinstance(value, str)) # True
2. Using == with type() unnecessarily
type(o) == str
This works for exact type comparison, but is better expresses that you are comparing type identity:
type(o) is str
3. Confusing type checking with conversion
value = "123"
print(isinstance(value, int)) # False
A string containing digits is still a string. If you need an integer, convert it:
number = int(value)
4. Expecting input() to return numbers automatically
age = input("Age: ")
print(isinstance(age, int)) # False
input() returns a string in Python 3. Convert it if needed:
age = int(input("Age: "))
5. Overusing type checks
Sometimes beginners write code like this:
def make_upper(value):
if isinstance(value, str):
return value.upper()
This returns None for non-strings and silently ignores problems. Often it is better to raise an error or rely on behavior.
Better:
def make_upper(value):
if not isinstance(value, str):
raise TypeError("value must be a string")
return value.upper()
6. Forgetting that bool is a subclass of int
print(isinstance(True, int)) # True
This surprises many beginners. If you want exactly int and not bool, use:
type(True) is int # False
type(5) is int # True
Comparisons
| Approach | What it checks | Inheritance-aware? | Typical use |
|---|---|---|---|
isinstance(obj, T) | Whether obj is an instance of T or a subclass of T | Yes | Most type checks |
type(obj) is T | Whether obj is exactly type T | No | Exact type match only |
type(obj) == T | Also checks exact type | No | Less preferred than is for types |
isinstance() vs type()
class Animal:
pass
class Dog(Animal):
pass
pet = Dog()
| Expression | Result |
|---|---|
isinstance(pet, Dog) | True |
isinstance(pet, Animal) | True |
type(pet) is Dog | True |
type(pet) is Animal | False |
Type checking vs duck typing
| Style | Idea | Example |
|---|---|---|
| Type checking | Ask what type the object is | isinstance(x, str) |
| Duck typing | Ask whether the object supports the needed operation | x.upper() |
Duck typing is often preferred in Python when behavior matters more than exact type.
Cheat Sheet
Quick rules
- Use
isinstance(obj, T)for most type checks. - Use
type(obj) is Tonly for exact matches. isinstance()supports inheritance.isinstance()can check multiple types with a tuple.
Common syntax
isinstance(obj, str)
isinstance(obj, (int, float, complex))
type(obj) is str
Examples
isinstance("hi", str) # True
type("hi") is str # True
class MyStr(str):
pass
s = MyStr("hello")
isinstance(s, str) # True
type(s) is str # False
Important edge case
isinstance(True, int) # True
type(True) is int # False
When to use what
- Want subclasses to count? Use
isinstance(). - Want the exact class only? Use
type() is. - Want to accept several types? Use
isinstance(obj, (A, B)). - Want to check behavior instead of class? Prefer duck typing when appropriate.
FAQ
Should I use isinstance() or type() in Python?
Usually use isinstance(). It correctly handles inheritance and is the standard choice for most checks.
How do I check if a value is a string in Python?
Use:
isinstance(value, str)
How do I check for an exact type in Python?
Use:
type(value) is str
This does not count subclasses.
Does isinstance() work with subclasses?
Yes. That is one of the main reasons it is preferred.
Can isinstance() check multiple types?
Yes:
isinstance(value, (int, float))
Why is isinstance(True, int) true?
In Python, bool is a subclass of int. If you need exact int, use type(value) is int.
Is type checking always Pythonic?
Not always. Python often prefers duck typing, where code uses an object based on what it can do rather than what exact type it is.
How do I check if an object inherits from a class?
For an object, use:
isinstance(obj, ParentClass)
If you are comparing classes themselves rather than objects, use issubclass().
Mini Project
Description
Build a small validation utility that checks whether incoming values match expected Python types. This mirrors real code where data enters from user input, APIs, or configuration files and must be validated before use.
Goal
Create a function that accepts a value and verifies whether it is a string, an exact integer, or one of several allowed types.
Requirements
- Write a function that checks whether a value is a string using
isinstance(). - Write a function that checks whether a value is exactly an
int, notbool. - Write a function that accepts values that are either
intorfloat. - Print clear results for several sample values.
- Use both
isinstance()andtype() iswhere each one makes sense.
Keep learning
Related questions
@staticmethod vs @classmethod in Python Explained
Learn the difference between @staticmethod and @classmethod in Python with clear examples, use cases, mistakes, and a mini project.
Add Rows to a Pandas DataFrame in Python
Learn how to add rows to a Pandas DataFrame, why repeated row appends are slow, and when to use loc, concat, or record lists.
Call a Function by Name in a Python Module
Learn how to call a function by name in a Python module using strings, getattr, and safe patterns for dynamic function dispatch.