Question
Is there a simple and reliable way in Python to determine whether a variable is a list, a dictionary, or another kind of object?
Short Answer
By the end of this page, you will understand how Python identifies object types, when to use type() versus isinstance(), and how to safely check whether a value is a list, dictionary, or another object in real programs.
Concept
In Python, every value is an object, and every object has a type.
For example:
[]is alist{}is adict"hello"is astr10is anint
To inspect an object's type, Python gives you two common tools:
type(obj)— returns the exact type of the objectisinstance(obj, SomeType)— checks whether the object is an instance of a type, including inherited types
In beginner code, type() often seems enough. But in real Python code, isinstance() is usually preferred because it works better with:
- inheritance
- custom classes
- subclasses of built-in types
- cleaner, more flexible validation
Why this matters
Type checking is useful when your code needs to behave differently depending on the input.
Examples:
- Accepting either a single value or a list of values
- Validating API input
- Handling JSON-like data structures
- Writing utility functions that support multiple input types
That said, Python also encourages duck typing: instead of asking "what type is this?", you often ask "can this object do what I need?" Still, explicit type checks are sometimes the clearest and safest option.
Mental Model
Think of every Python object as a package with a label on it.
type()reads the package's exact labelisinstance()asks whether the package belongs to a category
For example, imagine a class AdminUser that inherits from User:
type(admin)is exactlyAdminUserisinstance(admin, User)isTruebecause an admin is still a kind of user
So:
- use
type()when you need the exact label - use
isinstance()when you care about whether something fits a category
Syntax and Examples
The most common ways to check type in Python are:
value = [1, 2, 3]
print(type(value)) # <class 'list'>
print(isinstance(value, list)) # True
Checking for a list
value = [1, 2, 3]
if isinstance(value, list):
print("This is a list")
Checking for a dictionary
value = {"name": "Ada"}
if isinstance(value, dict):
print("This is a dictionary")
Checking multiple possible types
value = "hello"
if isinstance(value, (list, dict)):
print("Value is a list or dictionary")
else:
print("Value is something else")
Using type() for exact type comparison
value = [1, 2, 3]
if type(value) is list:
print("Exactly a list")
This works, but it only matches objects whose exact type is list. If you later use a subclass of list, this check will fail. That is why isinstance() is usually the better choice.
Example function
def describe_value(value):
if isinstance(value, list):
return "This value is a list"
elif isinstance(value, dict):
return "This value is a dictionary"
else:
return f"This value is a {type(value).__name__}"
print(describe_value([1, 2]))
print(describe_value({"a": 1}))
print(describe_value(42))
Output:
This value is a list
This value is a dictionary
This value is a int
Step by Step Execution
Consider this example:
def check_value(value):
if isinstance(value, list):
print("list")
elif isinstance(value, dict):
print("dict")
else:
print(type(value).__name__)
check_value([10, 20])
Step by step
- Python defines the function
check_value. - The function is called with
[10, 20]. - Inside the function,
valuerefers to the list[10, 20]. - Python evaluates
isinstance(value, list). - Since
[10, 20]is a list, the result isTrue. - Python prints
"list". - The
elifandelseblocks are skipped.
Another trace
check_value({"x": 1})
Execution:
valuebecomes{"x": 1}.isinstance(value, list)isFalse.isinstance(value, dict)isTrue.- Python prints
"dict".
Another trace
check_value(3.14)
Execution:
valuebecomes3.14.isinstance(value, list)isFalse.isinstance(value, dict)isFalse.type(value).__name__becomes"float".- Python prints
"float".
Real World Use Cases
Type checks appear in many real programs.
Processing JSON-like data
APIs often return nested dictionaries and lists.
def walk_data(data):
if isinstance(data, dict):
print("Object with keys:", list(data.keys()))
elif isinstance(data, list):
print("Array with", len(data), "items")
else:
print("Primitive value:", data)
Accepting flexible input
A function may accept either one item or many items.
def save_tags(tags):
if isinstance(tags, str):
tags = [tags]
print("Saving:", tags)
Validating configuration data
def validate_config(config):
if not isinstance(config, dict):
raise TypeError("config must be a dictionary")
Data cleaning scripts
When reading files or transforming mixed values, you may need to treat lists, strings, numbers, and dictionaries differently.
Real Codebase Usage
In real codebases, developers usually use type checks in a few common patterns.
Guard clauses
Validate inputs early and fail fast.
def process_user(user_data):
if not isinstance(user_data, dict):
raise TypeError("user_data must be a dict")
return user_data.get("name")
Early normalization
Convert different input forms into one predictable format.
def send_emails(addresses):
if isinstance(addresses, str):
addresses = [addresses]
for address in addresses:
print("Sending to", address)
Error handling
def total_numbers(values):
if not isinstance(values, list):
raise TypeError("values must be a list")
return sum(values)
Working with inheritance-friendly checks
Libraries often use isinstance() so subclasses still work correctly.
class MyList(list):
pass
items = MyList([1, 2, 3])
print(isinstance(items, list)) # True
When developers avoid type checks
Python code often prefers behavior-based design.
Instead of this:
if isinstance(obj, list):
...
developers sometimes write code that simply assumes the needed behavior and handles failure if it does not exist. This style is useful, but explicit type checks are still appropriate for validation and branching logic.
Common Mistakes
Here are common mistakes beginners make when checking types in Python.
1. Using type() when isinstance() is safer
Broken approach for subclass-friendly code:
class MyList(list):
pass
value = MyList([1, 2])
print(type(value) is list) # False
print(isinstance(value, list)) # True
Use isinstance() unless you specifically need the exact type.
2. Comparing type names as strings
Avoid this:
value = [1, 2, 3]
if type(value).__name__ == "list":
print("list")
This is less clear and less robust than:
if isinstance(value, list):
print("list")
3. Forgetting that bool is a subclass of int
print(isinstance(True, int)) # True
This surprises many beginners. If your code handles numbers specially, remember that booleans may match integer checks.
4. Overusing type checks
Sometimes you do not need to know the exact type. You only need an object that supports a certain operation.
For example, instead of checking whether something is a list, ask whether you can loop over it if iteration is all you need.
5. Using == instead of is with type()
If you do exact type comparison, write:
type(value) is list
not:
type(value) == list
is is clearer here because you are comparing type objects directly.
Comparisons
| Approach | Example | Best for | Subclasses supported? |
|---|---|---|---|
type() | type(value) | Inspecting the exact type | No |
| exact type check | type(value) is list | When only the exact type should match | No |
isinstance() | isinstance(value, list) | Most validation and branching | Yes |
| behavior-based check | try to use the object | Duck typing | Not based on type |
type() vs isinstance()
class MyDict(dict):
pass
value = MyDict()
print(type(value) is dict) # False
print(isinstance(value, dict)) # True
Use isinstance() when you want to know whether an object should be treated like a dictionary.
Type checking vs duck typing
def print_length(value):
print(len(value))
This function does not care whether value is a list, string, or tuple. It only cares that len(value) works.
That is the Python style known as duck typing: if it behaves like what you need, it is good enough.
Cheat Sheet
# Get exact type
type(value)
# Exact type check
type(value) is list
# Preferred general check
isinstance(value, list)
# Check for multiple types
isinstance(value, (list, dict))
# Get readable type name
type(value).__name__
Rules of thumb
- Use
isinstance()for most type checks. - Use
type()when you need the exact type object. - Use
type(value).__name__for readable messages. - Prefer behavior-based code when exact type does not matter.
Common built-in types
isinstance(value, list)
isinstance(value, dict)
isinstance(value, str)
isinstance(value, int)
isinstance(value, float)
isinstance(value, tuple)
Edge case
isinstance(True, int) # True
Remember that bool is a subclass of int in Python.
FAQ
How do I check if a variable is a list in Python?
Use:
isinstance(value, list)
This is the most common and recommended approach.
How do I check if a variable is a dictionary?
Use:
isinstance(value, dict)
Should I use type() or isinstance() in Python?
Usually use isinstance(). It supports inheritance and is more flexible in real applications.
How can I print the type name of an object?
Use:
type(value).__name__
This returns names like list, dict, or str.
Can isinstance() check more than one type?
Yes.
isinstance(value, (list, dict))
Why does isinstance(True, int) return True?
Because in Python, bool is a subclass of int.
Is checking type always the best Python style?
No. If your code only needs certain behavior, duck typing is often better. But type checks are still useful for validation and branching.
Mini Project
Description
Build a small Python utility that inspects values and reports what kind of object each one is. This mirrors a common real-world task when debugging, validating inputs, or exploring API data.
Goal
Create a function that identifies whether a value is a list, dictionary, string, number, or another type, and prints a readable message.
Requirements
- Write a function that accepts one value as input.
- Detect whether the value is a list, dictionary, string, integer, or float.
- Print a readable label for the detected type.
- For any other type, print the type name dynamically.
- Test the function with several different values.
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.