The type() built-in function operates in two distinct modes: inspecting an object's exact runtime type, or dynamically constructing new classes as a metaclass.
Introspection & Metaprogramming: When called with one argument, type(object) returns the exact class of the object. When called with three arguments (name, bases, dict), it dynamically builds and returns a new class at runtime. To check class inheritance polymorphically, see isinstance() and issubclass(). For the root base class of all objects, see object(), or inspect object memory addresses with id().
The type() function takes either one argument or three arguments:
# Formal syntax of built-in type()
# 1-argument form: inspection
obj_type = type(object)
# 3-argument form: dynamic class generation
ClassType = type(name, bases, dict, **kwds)
| Signature Mode | Parameters | Return Type | Operational Behavior |
|---|---|---|---|
| 1-Argument Form | type(object) |
type (the object's class) |
Returns the exact class of the passed object. |
| 3-Argument Form | type(name, bases, dict) |
type (new class constructor) |
Dynamically builds a new class object at runtime with given name, base tuples, and attribute mapping. |
Passing a single object returns its underlying type object:
# 1. Type inspection across primitives and sequences
print("Integer: ", type(42))
print("String: ", type("plus2net"))
print("List: ", type([1, 2, 3]))
print("NoneType: ", type(None))Terminal Output:
Integer: <class 'int'>
String: <class 'str'>
List: <class 'list'>
NoneType: <class 'NoneType'>
While type(obj) is Class tests for exact identity, isinstance() accounts for inheritance hierarchies:
# 2. type() vs. isinstance(): Exact match vs. Inheritance
flag = True
print("type(flag) is bool: ", type(flag) is bool)
print("type(flag) is int: ", type(flag) is int)
print("isinstance(flag, bool): ", isinstance(flag, bool))
print("isinstance(flag, int): ", isinstance(flag, int))Terminal Output:
type(flag) is bool: True
type(flag) is int: False
isinstance(flag, bool): True
isinstance(flag, int): True
Using type(name, bases, dict) allows generating classes dynamically on the fly without using the class keyword:
# 3. Dynamic class creation via 3-argument constructor
# type(name, bases, attributes_dict)
UserClass = type("UserClass", (object,), {
"role": "MEMBER",
"greet": lambda self, n: f"Hello, {n}!"
})
user = UserClass()
print("Class name: ", UserClass.__name__)
print("Instance call: ", user.greet("Alexander"))Terminal Output:
Class name: UserClass
Instance call: Hello, Alexander!
To convert between compatible types, call the specific type constructors: int(), float(), str(), complex(), or bool():
# 4. Converting data types using type constructors
num_str = "125"
num_int = int(num_str)
num_float = float(num_int)
num_complex = complex(num_int, 4)
print("Parsed int: ", num_int, type(num_int))
print("Converted float:", num_float, type(num_float))
print("Complex number: ", num_complex, type(num_complex))Terminal Output:
Parsed int: 125 <class 'int'>
Converted float: 125.0 <class 'float'>
Complex number: (125+4j) <class 'complex'>
phone_number = "+919876543210"
print(type(phone_number))
// Terminal Output: <class 'str'> (Preserves symbols and leading zeros!)
| Data Component | Sample Value | Python type() Output | Architect's Systems Reason |
|---|---|---|---|
| Phone Number | "+919876543210" |
<class 'str'> | Preserves leading zeros and symbols (+). No arithmetic needed. |
| Postal / PIN Code | "530003", "02108" |
<class 'str'> | Integers drop leading zeros (02108 → 2108), corrupting zip codes. |
| Vehicle Registration | "AP31AB1234" |
<class 'str'> | Alphanumeric text combining regional codes and registration sequences. |
| Product Stock / Qty | 50 |
<class 'int'> | Discrete whole counts used in arithmetic deductions during checkout. |
| Product Price / Tax | 199.50, 0.18 |
<class 'float'> | Fractional values with decimals required for monetary totals. |
| Account Status Flag | True, False |
<class 'bool'> | Binary state conditions controlling branch gates and permission flags. |
| Employee ID / SKU | "EMP0045" |
<class 'str'> | Unique text lookup identifier rather than a quantitative quantity. |
Using type() to dynamically construct structured model classes from schema definitions:
# 5. Production Recipe: Dynamic Model Factory
def make_record_class(model_name: str, fields: list):
"""Dynamically creates a model class from field definitions."""
def __init__(self, **kwargs):
for f in fields:
setattr(self, f, kwargs.get(f))
def __repr__(self):
items = ", ".join(f"{f}={getattr(self, f)!r}" for f in fields)
return f"{model_name}({items})"
return type(model_name, (object,), {"__init__": __init__, "__repr__": __repr__})
Product = make_record_class("Product", ["sku", "price"])
p = Product(sku="PROD-99", price=49.99)
print("Dynamic instance:", p)Terminal Output:
Dynamic instance: Product(sku='PROD-99', price=49.99)
Practice type inspection, dynamic class construction, and metaclass properties in our interactive companion Jupyter Notebook:
Explore interactive code cells, dynamically generate classes, test type vs isinstance comparisons, and run self-validating assertions.
View on GitHub Run in Google ColabRun these unit checks directly in Python or your local environment to verify type() mechanics:
# 7. Self-verifying unit test suite for type()
assert type(10) is int and type("text") is str and type([1, 2]) is list
class Base: pass
class Child(Base): pass
c = Child()
assert type(c) is Child and type(c) is not Base and isinstance(c, Base)
DynamicModel = type("DynamicModel", (), {"val": 100})
assert DynamicModel.val == 100 and isinstance(DynamicModel(), DynamicModel)
assert type(type) is type and issubclass(type, object)
print("All type() unit assertions successfully verified!")Terminal Output:
All type() unit assertions successfully verified!
Use type() when you need an exact type match without allowing subclasses. Use isinstance() when you want to support polymorphic subclassing.
Yes! Passing three arguments type(name, bases, dict) generates a fully functional new Python class at runtime.
In Python, type(type) is type. It is an instance of itself, functioning as the default metaclass for all classes.
Because in Python's class hierarchy, bool is a direct subclass of int (inheriting from integer 0 and 1).
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.