type()
Two very different jobs behind one name — reflection with one argument, class creation with three.
Common call
type(x) is int
Returns
a type object (class)
Replaces
the older x.__class__ attribute access — same result
Watch out
`type(x) == C` checks EXACT class; use isinstance() to include subclasses
type(object) / type(name, basesbases — (3-arg form) Tuple of base classes.type: tuple[type] · default: null, dictdict — (3-arg form) Attribute dict for the new class.type: dict · default: null)
→ type
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| object | Any | yes | Any value. type() returns its class — the same object as x.__class__. Never raises AttributeError; every value has a type. |
| name | str | no | (3-arg form) The name of the new class as a string. |
| bases | tuple[type] | no | (3-arg form) Tuple of base classes. |
| dict | dict | no | (3-arg form) Attribute dict for the new class. |
Return value
type — One-arg form: the object's type (its class). Three-arg form: a NEW class with the given name, bases, and attribute dict — this is the metaclass used to build classes.
Common patterns
Debug: what type is this?
A common diagnostic when something behaves unexpectedly.
print(f"got type={type(value).__name__}")
Exact class check
Use `is` for identity — type() returns the class itself.
if type(item) is dict: process_dict(item)
Prefer isinstance for subclass-aware checks
type() is exact; isinstance() covers subclasses.
# type(x) is int is False for a subclass of int # isinstance(x, int) is True for both
Dynamic class creation (advanced)
The three-arg form builds a class at runtime.
Point = type("Point", (), {"x": 0, "y": 0})
Examples
1. Text
type("hello")
Returns
<class 'str'>2. Integer
type(42)
Returns
<class 'int'>3. Float
type(3.14)
Returns
<class 'float'>4. Boolean
type(True)
Returns
<class 'bool'>5. None
type(None)
Returns
<class 'NoneType'>6. List
type([1, 2, 3])
Returns
<class 'list'>7. Compare with is
type(x) is str
Returns
True or False8. Just the name
type(x).__name__
Returns
"str" # a stringPitfalls
1. type() checks EXACT class — misses subclasses
The single most common type() mistake. `type(x) is int` is False for a bool (even though bool is a subclass of int). Use isinstance() when subclasses should count.
Bool missed
type(True) is int
False # bool is a subclass, not int itself
isinstance
isinstance(True, int)
True
2. Compare with `is`, not `==`
For typechecks, `is` and `==` usually give the same result, but `is` is the correct comparison for singleton objects like class instances. Consistency wins here.
Style noise
type(x) == int
works but non-idiomatic
Identity
type(x) is int
idiomatic
3. type(None) is NoneType, not None
None is a value; NoneType is its class. If you want to detect None, use `x is None` — the fastest and most idiomatic check.
Comparing to None
if type(x) is None:
always False — NoneType is a class
Direct check
if x is None:
idiomatic
4. The three-arg form is for advanced use only
Dynamic class creation is powerful but rarely necessary. If you find yourself reaching for `type("MyClass", ...)`, first consider a plain `class MyClass:` block, a dataclass, or namedtuple.
Over-engineered
Point = type("Point", (), {"x": 0, "y": 0})
works, but obscure
Plain class
class Point: x = 0 y = 0
clearer
When to use
Use it
- Debugging / diagnostic output — "what type is this?"
- Exact-class checks where subclasses should NOT count
- Reading `x.__class__` more idiomatically
- Dispatch tables keyed by exact class
Reach for something else
- Subclass-aware checks → isinstance is correct
- Detecting None → `x is None`
- Comparing with `==` — use `is` for identity
- Dynamic class creation without a strong reason — use a class block
Notes
Complexity
O(1) — direct attribute lookup on the object
Return
A type object (class)
CPython impl
Objects/typeobject.c :: type_new (constructor) and PyObject_Type (single-arg)
Memory
No allocation for single-arg; three-arg allocates a class
Thread-safe
Yes
FAQ
type(x) is C is True only when x is an INSTANCE of C — not a subclass. isinstance(x, C) is True for both. Use isinstance when subclasses should count (usually); use type() for exact-class dispatch.
History
1.0
type() has been a builtin since Python 1.0 — original name for the metaclass at the root.
3.0
Classic classes removed; every class now derives from object with type as the metaclass.