Photo by Lenny Kuhne / Unsplash

TIL - In Python type() With Three Arguments Is a Dynamic Class Factory

Today I Learned Apr 26, 2026

type(name, bases, namespace) is how Python creates every class - the class keyword is syntax sugar for it. Calling it directly lets you generate classes programmatically at runtime.

# These two are exactly equivalent:
class Greeter:
    greeting = "Hello"
    def greet(self, name): return f"{self.greeting}, {name}!"

Greeter2 = type("Greeter2", (object,), {
    "greeting": "Hello",
    "greet": lambda self, name: f"{self.greeting}, {name}!"
})

print(Greeter2().greet("World"))   # Hello, World!
# Dynamic subclassing — create an exception hierarchy at runtime
def make_error(name: str, base=Exception) -> type:
    return type(name, (base,), {"__module__": __name__})

NotFoundError  = make_error("NotFoundError")
ForbiddenError = make_error("ForbiddenError")

raise NotFoundError("item 42 not found")

This is the primitive that powers ORM field declarations, plugin systems, and serialization frameworks. Metaclasses are just subclasses of type that override __new__ or __init__ to hook into this process.

Tags